mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-21 02:54:20 +01:00
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:
@@ -1,6 +1,7 @@
|
||||
import base64
|
||||
import json
|
||||
import math
|
||||
import time
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
@@ -260,20 +261,7 @@ class BlindedSignature(BaseModel):
|
||||
)
|
||||
|
||||
|
||||
# ------- LIGHTNING INVOICE -------
|
||||
|
||||
|
||||
class Invoice(BaseModel):
|
||||
amount: int
|
||||
bolt11: str
|
||||
id: str
|
||||
out: Union[None, bool] = None
|
||||
payment_hash: Union[None, str] = None
|
||||
preimage: Union[str, None] = None
|
||||
issued: Union[None, bool] = False
|
||||
paid: Union[None, bool] = False
|
||||
time_created: Union[None, str, int, float] = ""
|
||||
time_paid: Union[None, str, int, float] = ""
|
||||
# ------- Quotes -------
|
||||
|
||||
|
||||
class MeltQuoteState(Enum):
|
||||
@@ -297,9 +285,10 @@ class MeltQuote(LedgerEvent):
|
||||
created_time: Union[int, None] = None
|
||||
paid_time: Union[int, None] = None
|
||||
fee_paid: int = 0
|
||||
payment_preimage: str = ""
|
||||
payment_preimage: Optional[str] = None
|
||||
expiry: Optional[int] = None
|
||||
change: Optional[List[BlindedSignature]] = None
|
||||
mint: Optional[str] = None
|
||||
|
||||
@classmethod
|
||||
def from_row(cls, row: Row):
|
||||
@@ -314,6 +303,8 @@ class MeltQuote(LedgerEvent):
|
||||
paid_time = int(row["paid_time"].timestamp()) if row["paid_time"] else None
|
||||
expiry = int(row["expiry"].timestamp()) if row["expiry"] else None
|
||||
|
||||
payment_preimage = row.get("payment_preimage") or row.get("proof") # type: ignore
|
||||
|
||||
# parse change from row as json
|
||||
change = None
|
||||
if row["change"]:
|
||||
@@ -327,13 +318,30 @@ class MeltQuote(LedgerEvent):
|
||||
unit=row["unit"],
|
||||
amount=row["amount"],
|
||||
fee_reserve=row["fee_reserve"],
|
||||
state=MeltQuoteState[row["state"]],
|
||||
state=MeltQuoteState(row["state"]),
|
||||
created_time=created_time,
|
||||
paid_time=paid_time,
|
||||
fee_paid=row["fee_paid"],
|
||||
change=change,
|
||||
expiry=expiry,
|
||||
payment_preimage=row["proof"],
|
||||
payment_preimage=payment_preimage,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_resp_wallet(
|
||||
cls, melt_quote_resp, mint: str, amount: int, unit: str, request: str
|
||||
):
|
||||
return cls(
|
||||
quote=melt_quote_resp.quote,
|
||||
method="bolt11",
|
||||
request=request,
|
||||
checking_id="",
|
||||
unit=unit,
|
||||
amount=amount,
|
||||
fee_reserve=melt_quote_resp.fee_reserve,
|
||||
state=MeltQuoteState(melt_quote_resp.state),
|
||||
mint=mint,
|
||||
change=melt_quote_resp.change,
|
||||
)
|
||||
|
||||
@property
|
||||
@@ -397,6 +405,7 @@ class MintQuote(LedgerEvent):
|
||||
created_time: Union[int, None] = None
|
||||
paid_time: Union[int, None] = None
|
||||
expiry: Optional[int] = None
|
||||
mint: Optional[str] = None
|
||||
|
||||
@classmethod
|
||||
def from_row(cls, row: Row):
|
||||
@@ -417,11 +426,26 @@ class MintQuote(LedgerEvent):
|
||||
checking_id=row["checking_id"],
|
||||
unit=row["unit"],
|
||||
amount=row["amount"],
|
||||
state=MintQuoteState[row["state"]],
|
||||
state=MintQuoteState(row["state"]),
|
||||
created_time=created_time,
|
||||
paid_time=paid_time,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_resp_wallet(cls, mint_quote_resp, mint: str, amount: int, unit: str):
|
||||
return cls(
|
||||
quote=mint_quote_resp.quote,
|
||||
method="bolt11",
|
||||
request=mint_quote_resp.request,
|
||||
checking_id="",
|
||||
unit=unit,
|
||||
amount=amount,
|
||||
state=MintQuoteState(mint_quote_resp.state),
|
||||
mint=mint,
|
||||
expiry=mint_quote_resp.expiry,
|
||||
created_time=int(time.time()),
|
||||
)
|
||||
|
||||
@property
|
||||
def identifier(self) -> str:
|
||||
"""Implementation of the abstract method from LedgerEventManager"""
|
||||
|
||||
@@ -65,6 +65,7 @@ class Compat:
|
||||
def table_with_schema(self, table: str):
|
||||
return f"{self.references_schema if self.schema else ''}{table}"
|
||||
|
||||
|
||||
# https://docs.sqlalchemy.org/en/14/core/connections.html#sqlalchemy.engine.CursorResult
|
||||
class Connection(Compat):
|
||||
def __init__(self, conn: AsyncSession, txn, typ, name, schema):
|
||||
@@ -82,7 +83,9 @@ class Connection(Compat):
|
||||
|
||||
async def fetchall(self, query: str, values: dict = {}):
|
||||
result = await self.conn.execute(self.rewrite_query(query), values)
|
||||
return [r._mapping for r in result.all()] # will return [] if result list is empty
|
||||
return [
|
||||
r._mapping for r in result.all()
|
||||
] # will return [] if result list is empty
|
||||
|
||||
async def fetchone(self, query: str, values: dict = {}):
|
||||
result = await self.conn.execute(self.rewrite_query(query), values)
|
||||
@@ -140,7 +143,7 @@ class Database(Compat):
|
||||
|
||||
self.engine = create_async_engine(database_uri, **kwargs)
|
||||
self.async_session = sessionmaker(
|
||||
self.engine,
|
||||
self.engine, # type: ignore
|
||||
expire_on_commit=False,
|
||||
class_=AsyncSession, # type: ignore
|
||||
)
|
||||
|
||||
@@ -304,7 +304,7 @@ class LedgerCrudSqlite(LedgerCrud):
|
||||
""",
|
||||
{"b_": str(b_)},
|
||||
)
|
||||
return BlindedSignature.from_row(row) if row else None
|
||||
return BlindedSignature.from_row(row) if row else None # type: ignore
|
||||
|
||||
async def get_promises(
|
||||
self,
|
||||
@@ -320,7 +320,7 @@ class LedgerCrudSqlite(LedgerCrud):
|
||||
""",
|
||||
{f"b_{i}": b_s[i] for i in range(len(b_s))},
|
||||
)
|
||||
return [BlindedSignature.from_row(r) for r in rows] if rows else []
|
||||
return [BlindedSignature.from_row(r) for r in rows] if rows else [] # type: ignore
|
||||
|
||||
async def invalidate_proof(
|
||||
self,
|
||||
@@ -455,7 +455,7 @@ class LedgerCrudSqlite(LedgerCrud):
|
||||
"amount": quote.amount,
|
||||
"paid": quote.paid, # this is deprecated! we need to store it because we have a NOT NULL constraint | we could also remove the column but sqlite doesn't support that (we would have to make a new table)
|
||||
"issued": quote.issued, # this is deprecated! we need to store it because we have a NOT NULL constraint | we could also remove the column but sqlite doesn't support that (we would have to make a new table)
|
||||
"state": quote.state.name,
|
||||
"state": quote.state.value,
|
||||
"created_time": db.to_timestamp(
|
||||
db.timestamp_from_seconds(quote.created_time) or ""
|
||||
),
|
||||
@@ -497,7 +497,7 @@ class LedgerCrudSqlite(LedgerCrud):
|
||||
)
|
||||
if row is None:
|
||||
return None
|
||||
return MintQuote.from_row(row) if row else None
|
||||
return MintQuote.from_row(row) if row else None # type: ignore
|
||||
|
||||
async def get_mint_quote_by_request(
|
||||
self,
|
||||
@@ -513,7 +513,7 @@ class LedgerCrudSqlite(LedgerCrud):
|
||||
""",
|
||||
{"request": request},
|
||||
)
|
||||
return MintQuote.from_row(row) if row else None
|
||||
return MintQuote.from_row(row) if row else None # type: ignore
|
||||
|
||||
async def update_mint_quote(
|
||||
self,
|
||||
@@ -525,7 +525,7 @@ class LedgerCrudSqlite(LedgerCrud):
|
||||
await (conn or db).execute(
|
||||
f"UPDATE {db.table_with_schema('mint_quotes')} SET state = :state, paid_time = :paid_time WHERE quote = :quote",
|
||||
{
|
||||
"state": quote.state.name,
|
||||
"state": quote.state.value,
|
||||
"paid_time": db.to_timestamp(
|
||||
db.timestamp_from_seconds(quote.paid_time) or ""
|
||||
),
|
||||
@@ -554,7 +554,7 @@ class LedgerCrudSqlite(LedgerCrud):
|
||||
"unit": quote.unit,
|
||||
"amount": quote.amount,
|
||||
"fee_reserve": quote.fee_reserve or 0,
|
||||
"state": quote.state.name,
|
||||
"state": quote.state.value,
|
||||
"paid": quote.paid, # this is deprecated! we need to store it because we have a NOT NULL constraint | we could also remove the column but sqlite doesn't support that (we would have to make a new table)
|
||||
"created_time": db.to_timestamp(
|
||||
db.timestamp_from_seconds(quote.created_time) or ""
|
||||
@@ -631,7 +631,7 @@ class LedgerCrudSqlite(LedgerCrud):
|
||||
UPDATE {db.table_with_schema('melt_quotes')} SET state = :state, fee_paid = :fee_paid, paid_time = :paid_time, proof = :proof, change = :change, checking_id = :checking_id WHERE quote = :quote
|
||||
""",
|
||||
{
|
||||
"state": quote.state.name,
|
||||
"state": quote.state.value,
|
||||
"fee_paid": quote.fee_paid,
|
||||
"paid_time": db.to_timestamp(
|
||||
db.timestamp_from_seconds(quote.paid_time) or ""
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import copy
|
||||
from typing import Dict, List
|
||||
|
||||
from ..core.base import MintKeyset, Proof
|
||||
from ..core.base import MeltQuoteState, MintKeyset, MintQuoteState, Proof
|
||||
from ..core.crypto.keys import derive_keyset_id, derive_keyset_id_deprecated
|
||||
from ..core.db import Connection, Database
|
||||
from ..core.settings import settings
|
||||
@@ -826,3 +826,15 @@ async def m021_add_change_and_expiry_to_melt_quotes(db: Database):
|
||||
await conn.execute(
|
||||
f"ALTER TABLE {db.table_with_schema('melt_quotes')} ADD COLUMN expiry TIMESTAMP"
|
||||
)
|
||||
|
||||
|
||||
async def m022_quote_set_states_to_values(db: Database):
|
||||
async with db.connect() as conn:
|
||||
for melt_quote_states in MeltQuoteState:
|
||||
await conn.execute(
|
||||
f"UPDATE {db.table_with_schema('melt_quotes')} SET state = '{melt_quote_states.value}' WHERE state = '{melt_quote_states.name}'"
|
||||
)
|
||||
for mint_quote_states in MintQuoteState:
|
||||
await conn.execute(
|
||||
f"UPDATE {db.table_with_schema('mint_quotes')} SET state = '{mint_quote_states.value}' WHERE state = '{mint_quote_states.name}'"
|
||||
)
|
||||
|
||||
@@ -2,23 +2,13 @@ from typing import Dict, List, Optional
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ...core.base import Invoice
|
||||
|
||||
|
||||
class PayResponse(BaseModel):
|
||||
ok: Optional[bool] = None
|
||||
|
||||
|
||||
class InvoiceResponse(BaseModel):
|
||||
amount: Optional[int] = None
|
||||
invoice: Optional[Invoice] = None
|
||||
id: Optional[str] = None
|
||||
from ...core.base import MeltQuote, MintQuote
|
||||
|
||||
|
||||
class SwapResponse(BaseModel):
|
||||
outgoing_mint: str
|
||||
incoming_mint: str
|
||||
invoice: Invoice
|
||||
mint_quote: MintQuote
|
||||
balances: Dict
|
||||
|
||||
|
||||
@@ -56,7 +46,8 @@ class LocksResponse(BaseModel):
|
||||
|
||||
|
||||
class InvoicesResponse(BaseModel):
|
||||
invoices: List[Invoice]
|
||||
mint_quotes: List[MintQuote]
|
||||
melt_quotes: List[MeltQuote]
|
||||
|
||||
|
||||
class WalletsResponse(BaseModel):
|
||||
|
||||
@@ -19,7 +19,11 @@ from ...lightning.base import (
|
||||
)
|
||||
from ...nostr.client.client import NostrClient
|
||||
from ...tor.tor import TorProxy
|
||||
from ...wallet.crud import get_lightning_invoices, get_reserved_proofs
|
||||
from ...wallet.crud import (
|
||||
get_bolt11_melt_quotes,
|
||||
get_bolt11_mint_quotes,
|
||||
get_reserved_proofs,
|
||||
)
|
||||
from ...wallet.helpers import (
|
||||
deserialize_token_from_string,
|
||||
init_wallet,
|
||||
@@ -141,7 +145,7 @@ async def create_invoice(
|
||||
response_model=PaymentStatus,
|
||||
)
|
||||
async def invoice_state(
|
||||
payment_hash: str = Query(default=None, description="Payment hash of paid invoice"),
|
||||
payment_request: str = Query(default=None, description="Payment request to check"),
|
||||
mint: str = Query(
|
||||
default=None,
|
||||
description="Mint URL to create an invoice at (None for default mint)",
|
||||
@@ -150,7 +154,7 @@ async def invoice_state(
|
||||
global wallet
|
||||
if mint:
|
||||
wallet = await mint_wallet(mint)
|
||||
state = await wallet.get_invoice_status(payment_hash)
|
||||
state = await wallet.get_invoice_status(payment_request)
|
||||
return state
|
||||
|
||||
|
||||
@@ -185,11 +189,11 @@ async def swap(
|
||||
raise Exception("mints for swap have to be different")
|
||||
|
||||
# request invoice from incoming mint
|
||||
invoice = await incoming_wallet.request_mint(amount)
|
||||
mint_quote = await incoming_wallet.request_mint(amount)
|
||||
|
||||
# pay invoice from outgoing mint
|
||||
await outgoing_wallet.load_proofs(reload=True)
|
||||
quote = await outgoing_wallet.melt_quote(invoice.bolt11)
|
||||
quote = await outgoing_wallet.melt_quote(mint_quote.request)
|
||||
total_amount = quote.amount + quote.fee_reserve
|
||||
if outgoing_wallet.available_balance < total_amount:
|
||||
raise Exception("balance too low")
|
||||
@@ -198,17 +202,17 @@ async def swap(
|
||||
outgoing_wallet.proofs, total_amount, set_reserved=True
|
||||
)
|
||||
await outgoing_wallet.melt(
|
||||
send_proofs, invoice.bolt11, quote.fee_reserve, quote.quote
|
||||
send_proofs, mint_quote.request, quote.fee_reserve, quote.quote
|
||||
)
|
||||
|
||||
# mint token in incoming mint
|
||||
await incoming_wallet.mint(amount, id=invoice.id)
|
||||
await incoming_wallet.mint(amount, quote_id=mint_quote.quote)
|
||||
await incoming_wallet.load_proofs(reload=True)
|
||||
mint_balances = await incoming_wallet.balance_per_minturl()
|
||||
return SwapResponse(
|
||||
outgoing_mint=outgoing_mint,
|
||||
incoming_mint=incoming_mint,
|
||||
invoice=invoice,
|
||||
mint_quote=mint_quote,
|
||||
balances=mint_balances,
|
||||
)
|
||||
|
||||
@@ -386,8 +390,9 @@ async def locks():
|
||||
"/invoices", name="List all pending invoices", response_model=InvoicesResponse
|
||||
)
|
||||
async def invoices():
|
||||
invoices = await get_lightning_invoices(db=wallet.db)
|
||||
return InvoicesResponse(invoices=invoices)
|
||||
mint_quotes = await get_bolt11_mint_quotes(db=wallet.db)
|
||||
melt_quotes = await get_bolt11_melt_quotes(db=wallet.db)
|
||||
return InvoicesResponse(mint_quotes=mint_quotes, melt_quotes=melt_quotes)
|
||||
|
||||
|
||||
@router.get(
|
||||
|
||||
@@ -15,7 +15,15 @@ import click
|
||||
from click import Context
|
||||
from loguru import logger
|
||||
|
||||
from ...core.base import Invoice, Method, MintQuoteState, TokenV4, Unit
|
||||
from ...core.base import (
|
||||
MeltQuote,
|
||||
MeltQuoteState,
|
||||
Method,
|
||||
MintQuote,
|
||||
MintQuoteState,
|
||||
TokenV4,
|
||||
Unit,
|
||||
)
|
||||
from ...core.helpers import sum_proofs
|
||||
from ...core.json_rpc.base import JSONRPCNotficationParams
|
||||
from ...core.logging import configure_logger
|
||||
@@ -24,8 +32,9 @@ from ...core.settings import settings
|
||||
from ...nostr.client.client import NostrClient
|
||||
from ...tor.tor import TorProxy
|
||||
from ...wallet.crud import (
|
||||
get_lightning_invoice,
|
||||
get_lightning_invoices,
|
||||
get_bolt11_melt_quotes,
|
||||
get_bolt11_mint_quote,
|
||||
get_bolt11_mint_quotes,
|
||||
get_reserved_proofs,
|
||||
get_seed_and_mnemonic,
|
||||
)
|
||||
@@ -302,7 +311,7 @@ async def invoice(
|
||||
)
|
||||
|
||||
paid = False
|
||||
invoice_nonlocal: Union[None, Invoice] = None
|
||||
invoice_nonlocal: Union[None, MintQuote] = None
|
||||
subscription_nonlocal: Union[None, SubscriptionManager] = None
|
||||
|
||||
def mint_invoice_callback(msg: JSONRPCNotficationParams):
|
||||
@@ -318,20 +327,24 @@ async def invoice(
|
||||
if paid:
|
||||
return
|
||||
try:
|
||||
quote = PostMintQuoteResponse.parse_obj(msg.payload)
|
||||
ws_quote_resp = PostMintQuoteResponse.parse_obj(msg.payload)
|
||||
except Exception:
|
||||
return
|
||||
logger.debug(f"Received callback for quote: {quote}")
|
||||
logger.debug(
|
||||
f"Received callback for quote: {ws_quote_resp.quote}: state {ws_quote_resp.state}"
|
||||
)
|
||||
# we need to sleep to give the callback map some time to be populated
|
||||
time.sleep(0.1)
|
||||
if (
|
||||
(quote.paid or quote.state == MintQuoteState.paid.value)
|
||||
and quote.request == invoice.bolt11
|
||||
(ws_quote_resp.state == MintQuoteState.paid.value)
|
||||
and ws_quote_resp.request == mint_quote.request
|
||||
and msg.subId in subscription.callback_map.keys()
|
||||
):
|
||||
try:
|
||||
asyncio.run(
|
||||
wallet.mint(int(amount), split=optional_split, id=invoice.id)
|
||||
wallet.mint(
|
||||
int(amount), split=optional_split, quote_id=mint_quote.quote
|
||||
)
|
||||
)
|
||||
# set paid so we won't react to any more callbacks
|
||||
paid = True
|
||||
@@ -348,21 +361,21 @@ async def invoice(
|
||||
Method["bolt11"], wallet.unit
|
||||
)
|
||||
if mint_supports_websockets and not no_check:
|
||||
invoice, subscription = await wallet.request_mint_with_callback(
|
||||
mint_quote, subscription = await wallet.request_mint_with_callback(
|
||||
amount, callback=mint_invoice_callback, memo=memo
|
||||
)
|
||||
invoice_nonlocal, subscription_nonlocal = invoice, subscription
|
||||
invoice_nonlocal, subscription_nonlocal = mint_quote, subscription
|
||||
else:
|
||||
invoice = await wallet.request_mint(amount, memo=memo)
|
||||
if invoice.bolt11:
|
||||
mint_quote = await wallet.request_mint(amount, memo=memo)
|
||||
if mint_quote.request:
|
||||
print("")
|
||||
print(f"Pay invoice to mint {wallet.unit.str(amount)}:")
|
||||
print("")
|
||||
print(f"Invoice: {invoice.bolt11}")
|
||||
print(f"Invoice: {mint_quote.request}")
|
||||
print("")
|
||||
print(
|
||||
"You can use this command to check the invoice: cashu invoice"
|
||||
f" {amount} --id {invoice.id}"
|
||||
f" {amount} --id {mint_quote.quote}"
|
||||
)
|
||||
if no_check:
|
||||
return
|
||||
@@ -381,9 +394,11 @@ async def invoice(
|
||||
while time.time() < check_until and not paid:
|
||||
await asyncio.sleep(5)
|
||||
try:
|
||||
mint_quote_resp = await wallet.get_mint_quote(invoice.id)
|
||||
mint_quote_resp = await wallet.get_mint_quote(mint_quote.quote)
|
||||
if mint_quote_resp.state == MintQuoteState.paid.value:
|
||||
await wallet.mint(amount, split=optional_split, id=invoice.id)
|
||||
await wallet.mint(
|
||||
amount, split=optional_split, quote_id=mint_quote.quote
|
||||
)
|
||||
paid = True
|
||||
else:
|
||||
print(".", end="", flush=True)
|
||||
@@ -403,7 +418,7 @@ async def invoice(
|
||||
|
||||
# user paid invoice before and wants to check the quote id
|
||||
elif amount and id:
|
||||
await wallet.mint(amount, split=optional_split, id=id)
|
||||
await wallet.mint(amount, split=optional_split, quote_id=id)
|
||||
|
||||
# close open subscriptions so we can exit
|
||||
try:
|
||||
@@ -422,10 +437,10 @@ async def invoice(
|
||||
@coro
|
||||
async def swap(ctx: Context):
|
||||
print("Select the mint to swap from:")
|
||||
outgoing_wallet = await get_mint_wallet(ctx, force_select=True)
|
||||
outgoing_wallet: Wallet = await get_mint_wallet(ctx, force_select=True)
|
||||
|
||||
print("Select the mint to swap to:")
|
||||
incoming_wallet = await get_mint_wallet(ctx, force_select=True)
|
||||
incoming_wallet: Wallet = await get_mint_wallet(ctx, force_select=True)
|
||||
|
||||
await incoming_wallet.load_mint()
|
||||
await outgoing_wallet.load_mint()
|
||||
@@ -437,22 +452,25 @@ async def swap(ctx: Context):
|
||||
assert amount > 0, "amount is not positive"
|
||||
|
||||
# request invoice from incoming mint
|
||||
invoice = await incoming_wallet.request_mint(amount)
|
||||
mint_quote = await incoming_wallet.request_mint(amount)
|
||||
|
||||
# pay invoice from outgoing mint
|
||||
quote = await outgoing_wallet.melt_quote(invoice.bolt11)
|
||||
total_amount = quote.amount + quote.fee_reserve
|
||||
melt_quote_resp = await outgoing_wallet.melt_quote(mint_quote.request)
|
||||
total_amount = melt_quote_resp.amount + melt_quote_resp.fee_reserve
|
||||
if outgoing_wallet.available_balance < total_amount:
|
||||
raise Exception("balance too low")
|
||||
send_proofs, fees = await outgoing_wallet.select_to_send(
|
||||
outgoing_wallet.proofs, total_amount, set_reserved=True
|
||||
)
|
||||
await outgoing_wallet.melt(
|
||||
send_proofs, invoice.bolt11, quote.fee_reserve, quote.quote
|
||||
send_proofs,
|
||||
mint_quote.request,
|
||||
melt_quote_resp.fee_reserve,
|
||||
melt_quote_resp.quote,
|
||||
)
|
||||
|
||||
# mint token in incoming mint
|
||||
await incoming_wallet.mint(amount, id=invoice.id)
|
||||
await incoming_wallet.mint(amount, quote_id=mint_quote.quote)
|
||||
|
||||
await incoming_wallet.load_proofs(reload=True)
|
||||
await print_mint_balances(incoming_wallet, show_mints=True)
|
||||
@@ -875,67 +893,85 @@ async def invoices(ctx, paid: bool, unpaid: bool, pending: bool, mint: bool):
|
||||
if mint:
|
||||
await wallet.load_mint()
|
||||
|
||||
paid_arg = None
|
||||
melt_state: MeltQuoteState | None = None
|
||||
mint_state: MintQuoteState | None = None
|
||||
if unpaid:
|
||||
paid_arg = False
|
||||
melt_state = MeltQuoteState.unpaid
|
||||
mint_state = MintQuoteState.unpaid
|
||||
elif paid:
|
||||
paid_arg = True
|
||||
melt_state = MeltQuoteState.paid
|
||||
mint_state = MintQuoteState.paid
|
||||
|
||||
invoices = await get_lightning_invoices(
|
||||
melt_quotes = await get_bolt11_melt_quotes(
|
||||
db=wallet.db,
|
||||
paid=paid_arg,
|
||||
pending=pending or None,
|
||||
state=melt_state,
|
||||
)
|
||||
|
||||
if len(invoices) == 0:
|
||||
mint_quotes = await get_bolt11_mint_quotes(
|
||||
db=wallet.db,
|
||||
state=mint_state,
|
||||
)
|
||||
|
||||
if len(melt_quotes) == 0 and len(mint_quotes) == 0:
|
||||
print("No invoices found.")
|
||||
return
|
||||
|
||||
async def _try_to_mint_pending_invoice(amount: int, id: str) -> Optional[Invoice]:
|
||||
async def _try_to_mint_pending_invoice(amount: int, id: str) -> Optional[MintQuote]:
|
||||
try:
|
||||
await wallet.mint(amount, id)
|
||||
return await get_lightning_invoice(db=wallet.db, id=id)
|
||||
proofs = await wallet.mint(amount, id)
|
||||
print(f"Received {wallet.unit.str(sum_proofs(proofs))}")
|
||||
return await get_bolt11_mint_quote(db=wallet.db, quote=id)
|
||||
except Exception as e:
|
||||
logger.error(f"Could not mint pending invoice [{id}]: {e}")
|
||||
logger.error(f"Could not mint pending invoice: {e}")
|
||||
return None
|
||||
|
||||
def _print_invoice_info(invoice: Invoice):
|
||||
def _print_quote_info(
|
||||
quote: MintQuote | MeltQuote | None, counter: int | None = None
|
||||
):
|
||||
print("\n--------------------------\n")
|
||||
print(f"Amount: {abs(invoice.amount)}")
|
||||
print(f"ID: {invoice.id}")
|
||||
print(f"Paid: {invoice.paid}")
|
||||
print(f"Incoming: {invoice.amount > 0}")
|
||||
if counter:
|
||||
print(f"#{counter}", end=" ")
|
||||
if isinstance(quote, MintQuote):
|
||||
print("Mint quote (incoming invoice)")
|
||||
elif isinstance(quote, MeltQuote):
|
||||
print("Melt quote (outgoing invoice)")
|
||||
else:
|
||||
return
|
||||
print(f"Amount: {abs(quote.amount)}")
|
||||
print(f"Mint: {quote.mint}")
|
||||
print(f"ID: {quote.quote}")
|
||||
print(f"State: {quote.state}")
|
||||
|
||||
if invoice.preimage:
|
||||
print(f"Preimage: {invoice.preimage}")
|
||||
if invoice.time_created:
|
||||
if isinstance(quote, MeltQuote):
|
||||
if quote.payment_preimage:
|
||||
print(f"Preimage: {quote.payment_preimage}")
|
||||
if quote.created_time:
|
||||
d = datetime.fromtimestamp(
|
||||
int(float(invoice.time_created)), timezone.utc
|
||||
int(float(quote.created_time)), timezone.utc
|
||||
).strftime("%Y-%m-%d %H:%M:%S")
|
||||
print(f"Created at: {d}")
|
||||
if invoice.time_paid:
|
||||
if quote.paid_time:
|
||||
d = datetime.fromtimestamp(
|
||||
(int(float(invoice.time_paid))), timezone.utc
|
||||
(int(float(quote.paid_time))), timezone.utc
|
||||
).strftime("%Y-%m-%d %H:%M:%S")
|
||||
print(f"Paid at: {d}")
|
||||
print(f"\nPayment request: {invoice.bolt11}")
|
||||
print(f"\nPayment request: {quote.request}")
|
||||
|
||||
invoices_printed_count = 0
|
||||
for invoice in invoices:
|
||||
is_pending_invoice = invoice.out is False and invoice.paid is False
|
||||
if is_pending_invoice and mint:
|
||||
# Tries to mint pending invoice
|
||||
updated_invoice = await _try_to_mint_pending_invoice(
|
||||
invoice.amount, invoice.id
|
||||
)
|
||||
# If the mint ran successfully and we are querying for pending or unpaid invoices, do not print it
|
||||
if pending or unpaid:
|
||||
continue
|
||||
# Otherwise, print the invoice with updated values
|
||||
if updated_invoice:
|
||||
invoice = updated_invoice
|
||||
for melt_quote in melt_quotes:
|
||||
_print_quote_info(melt_quote, invoices_printed_count + 1)
|
||||
invoices_printed_count += 1
|
||||
|
||||
_print_invoice_info(invoice)
|
||||
for mint_quote in mint_quotes:
|
||||
if mint_quote.state == MintQuoteState.unpaid and mint:
|
||||
# Tries to mint pending invoice
|
||||
mint_quote_pay = await _try_to_mint_pending_invoice(
|
||||
mint_quote.amount, mint_quote.quote
|
||||
)
|
||||
# If minting was successful, we don't need to print this invoice
|
||||
if mint_quote_pay:
|
||||
continue
|
||||
_print_quote_info(mint_quote, invoices_printed_count + 1)
|
||||
invoices_printed_count += 1
|
||||
|
||||
if invoices_printed_count == 0:
|
||||
|
||||
@@ -2,7 +2,14 @@ import json
|
||||
import time
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
from ..core.base import Invoice, Proof, WalletKeyset
|
||||
from ..core.base import (
|
||||
MeltQuote,
|
||||
MeltQuoteState,
|
||||
MintQuote,
|
||||
MintQuoteState,
|
||||
Proof,
|
||||
WalletKeyset,
|
||||
)
|
||||
from ..core.db import Connection, Database
|
||||
|
||||
|
||||
@@ -217,7 +224,7 @@ async def get_keysets(
|
||||
""",
|
||||
values,
|
||||
)
|
||||
return [WalletKeyset.from_row(r) for r in rows]
|
||||
return [WalletKeyset.from_row(r) for r in rows] # type: ignore
|
||||
|
||||
|
||||
async def update_keyset(
|
||||
@@ -238,83 +245,78 @@ async def update_keyset(
|
||||
)
|
||||
|
||||
|
||||
async def store_lightning_invoice(
|
||||
async def store_bolt11_mint_quote(
|
||||
db: Database,
|
||||
invoice: Invoice,
|
||||
quote: MintQuote,
|
||||
conn: Optional[Connection] = None,
|
||||
) -> None:
|
||||
await (conn or db).execute(
|
||||
"""
|
||||
INSERT INTO invoices
|
||||
(amount, bolt11, id, payment_hash, preimage, paid, time_created, time_paid, out)
|
||||
VALUES (:amount, :bolt11, :id, :payment_hash, :preimage, :paid, :time_created, :time_paid, :out)
|
||||
INSERT INTO bolt11_mint_quotes
|
||||
(quote, mint, method, request, checking_id, unit, amount, state, created_time, paid_time, expiry)
|
||||
VALUES (:quote, :mint, :method, :request, :checking_id, :unit, :amount, :state, :created_time, :paid_time, :expiry)
|
||||
""",
|
||||
{
|
||||
"amount": invoice.amount,
|
||||
"bolt11": invoice.bolt11,
|
||||
"id": invoice.id,
|
||||
"payment_hash": invoice.payment_hash,
|
||||
"preimage": invoice.preimage,
|
||||
"paid": invoice.paid,
|
||||
"time_created": invoice.time_created,
|
||||
"time_paid": invoice.time_paid,
|
||||
"out": invoice.out,
|
||||
"quote": quote.quote,
|
||||
"mint": quote.mint,
|
||||
"method": quote.method,
|
||||
"request": quote.request,
|
||||
"checking_id": quote.checking_id,
|
||||
"unit": quote.unit,
|
||||
"amount": quote.amount,
|
||||
"state": quote.state.value,
|
||||
"created_time": quote.created_time,
|
||||
"paid_time": quote.paid_time,
|
||||
"expiry": quote.expiry,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
async def get_lightning_invoice(
|
||||
*,
|
||||
async def get_bolt11_mint_quote(
|
||||
db: Database,
|
||||
id: str = "",
|
||||
payment_hash: str = "",
|
||||
out: Optional[bool] = None,
|
||||
quote: str | None = None,
|
||||
request: str | None = None,
|
||||
conn: Optional[Connection] = None,
|
||||
) -> Optional[Invoice]:
|
||||
) -> Optional[MintQuote]:
|
||||
if not quote and not request:
|
||||
raise ValueError("quote or request must be provided")
|
||||
clauses = []
|
||||
values: Dict[str, Any] = {}
|
||||
if id:
|
||||
clauses.append("id = :id")
|
||||
values["id"] = id
|
||||
if payment_hash:
|
||||
clauses.append("payment_hash = :payment_hash")
|
||||
values["payment_hash"] = payment_hash
|
||||
if out is not None:
|
||||
clauses.append("out = :out")
|
||||
values["out"] = out
|
||||
if quote:
|
||||
clauses.append("quote = :quote")
|
||||
values["quote"] = quote
|
||||
if request:
|
||||
clauses.append("request = :request")
|
||||
values["request"] = request
|
||||
|
||||
where = ""
|
||||
if clauses:
|
||||
where = f"WHERE {' AND '.join(clauses)}"
|
||||
query = f"""
|
||||
SELECT * from invoices
|
||||
{where}
|
||||
"""
|
||||
|
||||
row = await (conn or db).fetchone(
|
||||
query,
|
||||
f"""
|
||||
SELECT * from bolt11_mint_quotes
|
||||
{where}
|
||||
""",
|
||||
values,
|
||||
)
|
||||
return Invoice(**row) if row else None
|
||||
return MintQuote.from_row(row) if row else None # type: ignore
|
||||
|
||||
|
||||
async def get_lightning_invoices(
|
||||
async def get_bolt11_mint_quotes(
|
||||
db: Database,
|
||||
paid: Optional[bool] = None,
|
||||
pending: Optional[bool] = None,
|
||||
mint: Optional[str] = None,
|
||||
state: Optional[MintQuoteState] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
) -> List[Invoice]:
|
||||
) -> List[MintQuote]:
|
||||
clauses = []
|
||||
values: Dict[str, Any] = {}
|
||||
|
||||
if paid is not None and not pending:
|
||||
clauses.append("paid = :paid")
|
||||
values["paid"] = paid
|
||||
|
||||
if pending:
|
||||
clauses.append("paid = :paid")
|
||||
values["paid"] = False
|
||||
clauses.append("out = :out")
|
||||
values["out"] = False
|
||||
if mint:
|
||||
clauses.append("mint = :mint")
|
||||
values["mint"] = mint
|
||||
if state:
|
||||
clauses.append("state = :state")
|
||||
values["state"] = state.value
|
||||
|
||||
where = ""
|
||||
if clauses:
|
||||
@@ -322,37 +324,149 @@ async def get_lightning_invoices(
|
||||
|
||||
rows = await (conn or db).fetchall(
|
||||
f"""
|
||||
SELECT * from invoices
|
||||
SELECT * from bolt11_mint_quotes
|
||||
{where}
|
||||
""",
|
||||
values,
|
||||
)
|
||||
return [Invoice(**r) for r in rows]
|
||||
return [MintQuote.from_row(r) for r in rows] # type: ignore
|
||||
|
||||
|
||||
async def update_lightning_invoice(
|
||||
async def update_bolt11_mint_quote(
|
||||
db: Database,
|
||||
id: str,
|
||||
paid: bool,
|
||||
time_paid: Optional[int] = None,
|
||||
preimage: Optional[str] = None,
|
||||
quote: str,
|
||||
state: MintQuoteState,
|
||||
paid_time: int,
|
||||
conn: Optional[Connection] = None,
|
||||
) -> None:
|
||||
await (conn or db).execute(
|
||||
"""
|
||||
UPDATE bolt11_mint_quotes
|
||||
SET state = :state, paid_time = :paid_time
|
||||
WHERE quote = :quote
|
||||
""",
|
||||
{
|
||||
"state": state.value,
|
||||
"paid_time": paid_time,
|
||||
"quote": quote,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
async def store_bolt11_melt_quote(
|
||||
db: Database,
|
||||
quote: MeltQuote,
|
||||
conn: Optional[Connection] = None,
|
||||
) -> None:
|
||||
await (conn or db).execute(
|
||||
"""
|
||||
INSERT INTO bolt11_melt_quotes
|
||||
(quote, mint, method, request, checking_id, unit, amount, fee_reserve, state, created_time, paid_time, fee_paid, payment_preimage, expiry, change)
|
||||
VALUES (:quote, :mint, :method, :request, :checking_id, :unit, :amount, :fee_reserve, :state, :created_time, :paid_time, :fee_paid, :payment_preimage, :expiry, :change)
|
||||
""",
|
||||
{
|
||||
"quote": quote.quote,
|
||||
"mint": quote.mint,
|
||||
"method": quote.method,
|
||||
"request": quote.request,
|
||||
"checking_id": quote.checking_id,
|
||||
"unit": quote.unit,
|
||||
"amount": quote.amount,
|
||||
"fee_reserve": quote.fee_reserve,
|
||||
"state": quote.state.value,
|
||||
"created_time": quote.created_time,
|
||||
"paid_time": quote.paid_time,
|
||||
"fee_paid": quote.fee_paid,
|
||||
"payment_preimage": quote.payment_preimage,
|
||||
"expiry": quote.expiry,
|
||||
"change": (
|
||||
json.dumps([c.dict() for c in quote.change]) if quote.change else ""
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
async def get_bolt11_melt_quote(
|
||||
db: Database,
|
||||
quote: Optional[str] = None,
|
||||
request: Optional[str] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
) -> Optional[MeltQuote]:
|
||||
if not quote and not request:
|
||||
raise ValueError("quote or request must be provided")
|
||||
clauses = []
|
||||
values: Dict[str, Any] = {}
|
||||
clauses.append("paid = :paid")
|
||||
values["paid"] = paid
|
||||
if quote:
|
||||
clauses.append("quote = :quote")
|
||||
values["quote"] = quote
|
||||
if request:
|
||||
clauses.append("request = :request")
|
||||
values["request"] = request
|
||||
|
||||
if time_paid:
|
||||
clauses.append("time_paid = :time_paid")
|
||||
values["time_paid"] = time_paid
|
||||
if preimage:
|
||||
clauses.append("preimage = :preimage")
|
||||
values["preimage"] = preimage
|
||||
where = ""
|
||||
if clauses:
|
||||
where = f"WHERE {' AND '.join(clauses)}"
|
||||
row = await (conn or db).fetchone(
|
||||
f"""
|
||||
SELECT * from bolt11_melt_quotes
|
||||
{where}
|
||||
""",
|
||||
values,
|
||||
)
|
||||
|
||||
return MeltQuote.from_row(row) if row else None # type: ignore
|
||||
|
||||
|
||||
async def get_bolt11_melt_quotes(
|
||||
db: Database,
|
||||
mint: Optional[str] = None,
|
||||
state: Optional[MeltQuoteState] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
) -> List[MeltQuote]:
|
||||
clauses = []
|
||||
values: Dict[str, Any] = {}
|
||||
if mint:
|
||||
clauses.append("mint = :mint")
|
||||
values["mint"] = mint
|
||||
if state:
|
||||
clauses.append("state = :state")
|
||||
values["state"] = state.value
|
||||
|
||||
where = ""
|
||||
if clauses:
|
||||
where = f"WHERE {' AND '.join(clauses)}"
|
||||
rows = await (conn or db).fetchall(
|
||||
f"""
|
||||
SELECT * from bolt11_melt_quotes
|
||||
{where}
|
||||
""",
|
||||
values,
|
||||
)
|
||||
return [MeltQuote.from_row(r) for r in rows] # type: ignore
|
||||
|
||||
|
||||
async def update_bolt11_melt_quote(
|
||||
db: Database,
|
||||
quote: str,
|
||||
state: MeltQuoteState,
|
||||
paid_time: int,
|
||||
fee_paid: int,
|
||||
payment_preimage: str,
|
||||
conn: Optional[Connection] = None,
|
||||
) -> None:
|
||||
await (conn or db).execute(
|
||||
f"UPDATE invoices SET {', '.join(clauses)} WHERE id = :id",
|
||||
{**values, "id": id},
|
||||
"""
|
||||
UPDATE bolt11_melt_quotes
|
||||
SET state = :state, paid_time = :paid_time, fee_paid = :fee_paid, payment_preimage = :payment_preimage
|
||||
WHERE quote = :quote
|
||||
""",
|
||||
{
|
||||
"state": state.value,
|
||||
"paid_time": paid_time,
|
||||
"fee_paid": fee_paid,
|
||||
"payment_preimage": payment_preimage,
|
||||
"quote": quote,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -423,7 +537,7 @@ async def get_nostr_last_check_timestamp(
|
||||
""",
|
||||
{"type": "dm"},
|
||||
)
|
||||
return row[0] if row else None
|
||||
return row[0] if row else None # type: ignore
|
||||
|
||||
|
||||
async def get_seed_and_mnemonic(
|
||||
|
||||
@@ -12,7 +12,11 @@ from ...lightning.base import (
|
||||
PaymentStatus,
|
||||
StatusResponse,
|
||||
)
|
||||
from ...wallet.crud import get_lightning_invoice, get_proofs
|
||||
from ...wallet.crud import (
|
||||
get_bolt11_melt_quote,
|
||||
get_bolt11_mint_quote,
|
||||
get_proofs,
|
||||
)
|
||||
from ..wallet import Wallet
|
||||
|
||||
|
||||
@@ -47,21 +51,22 @@ class LightningWallet(Wallet):
|
||||
Returns:
|
||||
str: invoice
|
||||
"""
|
||||
invoice = await self.request_mint(amount, memo)
|
||||
mint_quote = await self.request_mint(amount, memo)
|
||||
return InvoiceResponse(
|
||||
ok=True, payment_request=invoice.bolt11, checking_id=invoice.payment_hash
|
||||
ok=True,
|
||||
payment_request=mint_quote.request,
|
||||
)
|
||||
|
||||
async def pay_invoice(self, pr: str) -> PaymentResponse:
|
||||
async def pay_invoice(self, request: str) -> PaymentResponse:
|
||||
"""Pay lightning invoice
|
||||
|
||||
Args:
|
||||
pr (str): bolt11 payment request
|
||||
request (str): bolt11 payment request
|
||||
|
||||
Returns:
|
||||
PaymentResponse: containing details of the operation
|
||||
"""
|
||||
quote = await self.melt_quote(pr)
|
||||
quote = await self.melt_quote(request)
|
||||
total_amount = quote.amount + quote.fee_reserve
|
||||
assert total_amount > 0, "amount is not positive"
|
||||
if self.available_balance < total_amount:
|
||||
@@ -69,13 +74,13 @@ class LightningWallet(Wallet):
|
||||
return PaymentResponse(result=PaymentResult.FAILED)
|
||||
_, send_proofs = await self.swap_to_send(self.proofs, total_amount)
|
||||
try:
|
||||
resp = await self.melt(send_proofs, pr, quote.fee_reserve, quote.quote)
|
||||
resp = await self.melt(send_proofs, request, quote.fee_reserve, quote.quote)
|
||||
if resp.change:
|
||||
fees_paid_sat = quote.fee_reserve - sum_promises(resp.change)
|
||||
else:
|
||||
fees_paid_sat = quote.fee_reserve
|
||||
|
||||
invoice_obj = bolt11.decode(pr)
|
||||
invoice_obj = bolt11.decode(request)
|
||||
return PaymentResponse(
|
||||
result=PaymentResult.SETTLED,
|
||||
checking_id=invoice_obj.payment_hash,
|
||||
@@ -86,55 +91,49 @@ class LightningWallet(Wallet):
|
||||
print("Exception:", e)
|
||||
return PaymentResponse(result=PaymentResult.FAILED, error_message=str(e))
|
||||
|
||||
async def get_invoice_status(self, payment_hash: str) -> PaymentStatus:
|
||||
async def get_invoice_status(self, request: str) -> PaymentStatus:
|
||||
"""Get lightning invoice status (incoming)
|
||||
|
||||
Args:
|
||||
invoice (str): lightning invoice
|
||||
request (str): lightning invoice request
|
||||
|
||||
Returns:
|
||||
str: status
|
||||
"""
|
||||
invoice = await get_lightning_invoice(
|
||||
db=self.db, payment_hash=payment_hash, out=False
|
||||
)
|
||||
if not invoice:
|
||||
mint_quote = await get_bolt11_mint_quote(db=self.db, request=request)
|
||||
if not mint_quote:
|
||||
return PaymentStatus(result=PaymentResult.UNKNOWN)
|
||||
if invoice.paid:
|
||||
if mint_quote.paid:
|
||||
return PaymentStatus(result=PaymentResult.SETTLED)
|
||||
try:
|
||||
# to check the invoice state, we try minting tokens
|
||||
await self.mint(invoice.amount, id=invoice.id)
|
||||
await self.mint(mint_quote.amount, quote_id=mint_quote.quote)
|
||||
return PaymentStatus(result=PaymentResult.SETTLED)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return PaymentStatus(result=PaymentResult.FAILED)
|
||||
|
||||
async def get_payment_status(self, payment_hash: str) -> PaymentStatus:
|
||||
async def get_payment_status(self, request: str) -> PaymentStatus:
|
||||
"""Get lightning payment status (outgoing)
|
||||
|
||||
Args:
|
||||
payment_hash (str): lightning invoice payment_hash
|
||||
request (str): lightning invoice request
|
||||
|
||||
Returns:
|
||||
str: status
|
||||
"""
|
||||
|
||||
# NOTE: consider adding this in wallet.py and update invoice state to paid in DB
|
||||
melt_quote = await get_bolt11_melt_quote(db=self.db, request=request)
|
||||
|
||||
invoice = await get_lightning_invoice(
|
||||
db=self.db, payment_hash=payment_hash, out=True
|
||||
)
|
||||
|
||||
if not invoice:
|
||||
if not melt_quote:
|
||||
return PaymentStatus(
|
||||
result=PaymentResult.FAILED
|
||||
) # "invoice not found (in db)"
|
||||
if invoice.paid:
|
||||
if melt_quote.paid:
|
||||
return PaymentStatus(
|
||||
result=PaymentResult.SETTLED, preimage=invoice.preimage
|
||||
result=PaymentResult.SETTLED, preimage=melt_quote.payment_preimage
|
||||
) # "paid (in db)"
|
||||
proofs = await get_proofs(db=self.db, melt_id=invoice.id)
|
||||
proofs = await get_proofs(db=self.db, melt_id=melt_quote.quote)
|
||||
if not proofs:
|
||||
return PaymentStatus(
|
||||
result=PaymentResult.FAILED
|
||||
|
||||
@@ -245,79 +245,44 @@ async def m012_add_fee_to_keysets(db: Database):
|
||||
await conn.execute("UPDATE keysets SET input_fee_ppk = 0")
|
||||
|
||||
|
||||
# # async def m020_add_state_to_mint_and_melt_quotes(db: Database):
|
||||
# # async with db.connect() as conn:
|
||||
# # await conn.execute(
|
||||
# # f"ALTER TABLE {db.table_with_schema('mint_quotes')} ADD COLUMN state TEXT"
|
||||
# # )
|
||||
# # await conn.execute(
|
||||
# # f"ALTER TABLE {db.table_with_schema('melt_quotes')} ADD COLUMN state TEXT"
|
||||
# # )
|
||||
async def m013_add_mint_and_melt_quote_tables(db: Database):
|
||||
async with db.connect() as conn:
|
||||
await conn.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS bolt11_mint_quotes (
|
||||
quote TEXT PRIMARY KEY,
|
||||
mint TEXT NOT NULL,
|
||||
method TEXT NOT NULL,
|
||||
request TEXT NOT NULL,
|
||||
checking_id TEXT NOT NULL,
|
||||
unit TEXT NOT NULL,
|
||||
amount INTEGER NOT NULL,
|
||||
state TEXT NOT NULL,
|
||||
created_time INTEGER,
|
||||
paid_time INTEGER,
|
||||
expiry INTEGER
|
||||
);
|
||||
"""
|
||||
)
|
||||
|
||||
# # # get all melt and mint quotes and figure out the state to set using the `paid` column
|
||||
# # # and the `paid` and `issued` column respectively
|
||||
# # # mint quotes:
|
||||
# # async with db.connect() as conn:
|
||||
# # rows = await conn.fetchall(
|
||||
# # f"SELECT * FROM {db.table_with_schema('mint_quotes')}"
|
||||
# # )
|
||||
# # for row in rows:
|
||||
# # if row["issued"]:
|
||||
# # state = "issued"
|
||||
# # elif row["paid"]:
|
||||
# # state = "paid"
|
||||
# # else:
|
||||
# # state = "unpaid"
|
||||
# # await conn.execute(
|
||||
# # f"UPDATE {db.table_with_schema('mint_quotes')} SET state = '{state}' WHERE quote = '{row['quote']}'"
|
||||
# # )
|
||||
|
||||
# # # melt quotes:
|
||||
# # async with db.connect() as conn:
|
||||
# # rows = await conn.fetchall(
|
||||
# # f"SELECT * FROM {db.table_with_schema('melt_quotes')}"
|
||||
# # )
|
||||
# # for row in rows:
|
||||
# # if row["paid"]:
|
||||
# # state = "paid"
|
||||
# # else:
|
||||
# # state = "unpaid"
|
||||
# # await conn.execute(
|
||||
# # f"UPDATE {db.table_with_schema('melt_quotes')} SET state = '{state}' WHERE quote = '{row['quote']}'"
|
||||
# # )
|
||||
# # add the equivalent of the above migration for the wallet here. do not use table_with_schema. use the tables and columns
|
||||
# # as they are defined in the wallet db
|
||||
|
||||
|
||||
# async def m020_add_state_to_mint_and_melt_quotes(db: Database):
|
||||
# async with db.connect() as conn:
|
||||
# await conn.execute("ALTER TABLE mint_quotes ADD COLUMN state TEXT")
|
||||
# await conn.execute("ALTER TABLE melt_quotes ADD COLUMN state TEXT")
|
||||
|
||||
# # get all melt and mint quotes and figure out the state to set using the `paid` column
|
||||
# # and the `paid` and `issued` column respectively
|
||||
# # mint quotes:
|
||||
# async with db.connect() as conn:
|
||||
# rows = await conn.fetchall("SELECT * FROM mint_quotes")
|
||||
# for row in rows:
|
||||
# if row["issued"]:
|
||||
# state = "issued"
|
||||
# elif row["paid"]:
|
||||
# state = "paid"
|
||||
# else:
|
||||
# state = "unpaid"
|
||||
# await conn.execute(
|
||||
# f"UPDATE mint_quotes SET state = '{state}' WHERE quote = '{row['quote']}'"
|
||||
# )
|
||||
|
||||
# # melt quotes:
|
||||
# async with db.connect() as conn:
|
||||
# rows = await conn.fetchall("SELECT * FROM melt_quotes")
|
||||
# for row in rows:
|
||||
# if row["paid"]:
|
||||
# state = "paid"
|
||||
# else:
|
||||
# state = "unpaid"
|
||||
# await conn.execute(
|
||||
# f"UPDATE melt_quotes SET state = '{state}' WHERE quote = '{row['quote']}'"
|
||||
# )
|
||||
await conn.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS bolt11_melt_quotes (
|
||||
quote TEXT PRIMARY KEY,
|
||||
mint TEXT NOT NULL,
|
||||
method TEXT NOT NULL,
|
||||
request TEXT NOT NULL,
|
||||
checking_id TEXT NOT NULL,
|
||||
unit TEXT NOT NULL,
|
||||
amount INTEGER NOT NULL,
|
||||
fee_reserve INTEGER NOT NULL,
|
||||
state TEXT NOT NULL,
|
||||
created_time INTEGER,
|
||||
paid_time INTEGER,
|
||||
fee_paid INTEGER,
|
||||
payment_preimage TEXT,
|
||||
expiry INTEGER,
|
||||
change TEXT
|
||||
);
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -9,6 +9,8 @@ from httpx import Response
|
||||
from loguru import logger
|
||||
from pydantic import ValidationError
|
||||
|
||||
from cashu.wallet.crud import get_bolt11_melt_quote
|
||||
|
||||
from ..core.base import (
|
||||
BlindedMessage,
|
||||
BlindedSignature,
|
||||
@@ -45,9 +47,6 @@ from ..core.models import (
|
||||
)
|
||||
from ..core.settings import settings
|
||||
from ..tor.tor import TorProxy
|
||||
from .crud import (
|
||||
get_lightning_invoice,
|
||||
)
|
||||
from .wallet_deprecated import LedgerAPIDeprecated
|
||||
|
||||
|
||||
@@ -476,10 +475,10 @@ class LedgerAPI(LedgerAPIDeprecated):
|
||||
# BEGIN backwards compatibility < 0.15.0
|
||||
# assume the mint has not upgraded yet if we get a 404
|
||||
if resp.status_code == 404:
|
||||
invoice = await get_lightning_invoice(id=quote, db=self.db)
|
||||
assert invoice, f"no invoice found for id {quote}"
|
||||
melt_quote = await get_bolt11_melt_quote(quote=quote, db=self.db)
|
||||
assert melt_quote, f"no melt_quote found for id {quote}"
|
||||
ret: PostMeltResponse_deprecated = await self.melt_deprecated(
|
||||
proofs=proofs, outputs=outputs, invoice=invoice.bolt11
|
||||
proofs=proofs, outputs=outputs, invoice=melt_quote.request
|
||||
)
|
||||
elif isinstance(e, ValidationError):
|
||||
# BEGIN backwards compatibility < 0.16.0
|
||||
|
||||
@@ -4,7 +4,6 @@ import threading
|
||||
import time
|
||||
from typing import Callable, Dict, List, Optional, Tuple, Union
|
||||
|
||||
import bolt11
|
||||
from bip32 import BIP32
|
||||
from loguru import logger
|
||||
|
||||
@@ -12,8 +11,10 @@ from ..core.base import (
|
||||
BlindedMessage,
|
||||
BlindedSignature,
|
||||
DLEQWallet,
|
||||
Invoice,
|
||||
MeltQuote,
|
||||
MeltQuoteState,
|
||||
MintQuote,
|
||||
MintQuoteState,
|
||||
Proof,
|
||||
Unit,
|
||||
WalletKeyset,
|
||||
@@ -26,6 +27,7 @@ from ..core.errors import KeysetNotFoundError
|
||||
from ..core.helpers import (
|
||||
amount_summary,
|
||||
calculate_number_of_blank_outputs,
|
||||
sum_promises,
|
||||
sum_proofs,
|
||||
)
|
||||
from ..core.json_rpc.base import JSONRPCSubscriptionKinds
|
||||
@@ -45,11 +47,13 @@ from .crud import (
|
||||
invalidate_proof,
|
||||
secret_used,
|
||||
set_secret_derivation,
|
||||
store_bolt11_melt_quote,
|
||||
store_bolt11_mint_quote,
|
||||
store_keyset,
|
||||
store_lightning_invoice,
|
||||
store_proof,
|
||||
update_bolt11_melt_quote,
|
||||
update_bolt11_mint_quote,
|
||||
update_keyset,
|
||||
update_lightning_invoice,
|
||||
update_proof,
|
||||
)
|
||||
from .htlc import WalletHTLC
|
||||
@@ -312,7 +316,9 @@ class Wallet(
|
||||
|
||||
self.keyset_id = chosen_keyset.id
|
||||
|
||||
logger.debug(f"Activated keyset {self.keyset_id}")
|
||||
logger.debug(
|
||||
f"Activated keyset {self.keyset_id} ({self.keysets[self.keyset_id].unit}) fee: {self.keysets[self.keyset_id].input_fee_ppk}"
|
||||
)
|
||||
|
||||
async def load_mint(self, keyset_id: str = "", force_old_keysets=False) -> None:
|
||||
"""
|
||||
@@ -381,8 +387,8 @@ class Wallet(
|
||||
|
||||
async def request_mint_with_callback(
|
||||
self, amount: int, callback: Callable, memo: Optional[str] = None
|
||||
) -> Tuple[Invoice, SubscriptionManager]:
|
||||
"""Request a Lightning invoice for minting tokens.
|
||||
) -> Tuple[MintQuote, SubscriptionManager]:
|
||||
"""Request a quote invoice for minting tokens.
|
||||
|
||||
Args:
|
||||
amount (int): Amount for Lightning invoice in satoshis
|
||||
@@ -390,7 +396,7 @@ class Wallet(
|
||||
memo (Optional[str], optional): Memo for the Lightning invoice. Defaults
|
||||
|
||||
Returns:
|
||||
Invoice: Lightning invoice
|
||||
MintQuote: Mint Quote
|
||||
"""
|
||||
mint_qoute = await super().mint_quote(amount, self.unit, memo)
|
||||
subscriptions = SubscriptionManager(self.url)
|
||||
@@ -402,21 +408,13 @@ class Wallet(
|
||||
filters=[mint_qoute.quote],
|
||||
callback=callback,
|
||||
)
|
||||
# return the invoice
|
||||
decoded_invoice = bolt11.decode(mint_qoute.request)
|
||||
invoice = Invoice(
|
||||
amount=amount,
|
||||
bolt11=mint_qoute.request,
|
||||
payment_hash=decoded_invoice.payment_hash,
|
||||
id=mint_qoute.quote,
|
||||
out=False,
|
||||
time_created=int(time.time()),
|
||||
)
|
||||
await store_lightning_invoice(db=self.db, invoice=invoice)
|
||||
return invoice, subscriptions
|
||||
quote = MintQuote.from_resp_wallet(mint_qoute, self.url, amount, self.unit.name)
|
||||
await store_bolt11_mint_quote(db=self.db, quote=quote)
|
||||
|
||||
async def request_mint(self, amount: int, memo: Optional[str] = None) -> Invoice:
|
||||
"""Request a Lightning invoice for minting tokens.
|
||||
return quote, subscriptions
|
||||
|
||||
async def request_mint(self, amount: int, memo: Optional[str] = None) -> MintQuote:
|
||||
"""Request a quote invoice for minting tokens.
|
||||
|
||||
Args:
|
||||
amount (int): Amount for Lightning invoice in satoshis
|
||||
@@ -424,20 +422,14 @@ class Wallet(
|
||||
memo (Optional[str], optional): Memo for the Lightning invoice. Defaults to None.
|
||||
|
||||
Returns:
|
||||
PostMintQuoteResponse: Mint Quote Response
|
||||
MintQuote: Mint Quote
|
||||
"""
|
||||
mint_quote_response = await super().mint_quote(amount, self.unit, memo)
|
||||
decoded_invoice = bolt11.decode(mint_quote_response.request)
|
||||
invoice = Invoice(
|
||||
amount=amount,
|
||||
bolt11=mint_quote_response.request,
|
||||
payment_hash=decoded_invoice.payment_hash,
|
||||
id=mint_quote_response.quote,
|
||||
out=False,
|
||||
time_created=int(time.time()),
|
||||
quote = MintQuote.from_resp_wallet(
|
||||
mint_quote_response, self.url, amount, self.unit.name
|
||||
)
|
||||
await store_lightning_invoice(db=self.db, invoice=invoice)
|
||||
return invoice
|
||||
await store_bolt11_mint_quote(db=self.db, quote=quote)
|
||||
return quote
|
||||
|
||||
def split_wallet_state(self, amount: int) -> List[int]:
|
||||
"""This function produces an amount split for outputs based on the current state of the wallet.
|
||||
@@ -484,33 +476,10 @@ class Wallet(
|
||||
|
||||
return amounts
|
||||
|
||||
async def mint_quote(self, amount: int, memo: Optional[str] = None) -> Invoice:
|
||||
"""Request a Lightning invoice for minting tokens.
|
||||
|
||||
Args:
|
||||
amount (int): Amount for Lightning invoice in satoshis
|
||||
memo (Optional[str], optional): Memo for the Lightning invoice. Defaults to None.
|
||||
|
||||
Returns:
|
||||
Invoice: Lightning invoice for minting tokens
|
||||
"""
|
||||
mint_quote_response = await super().mint_quote(amount, self.unit)
|
||||
decoded_invoice = bolt11.decode(mint_quote_response.request)
|
||||
invoice = Invoice(
|
||||
amount=amount,
|
||||
bolt11=mint_quote_response.request,
|
||||
payment_hash=decoded_invoice.payment_hash,
|
||||
id=mint_quote_response.quote,
|
||||
out=False,
|
||||
time_created=int(time.time()),
|
||||
)
|
||||
await store_lightning_invoice(db=self.db, invoice=invoice)
|
||||
return invoice
|
||||
|
||||
async def mint(
|
||||
self,
|
||||
amount: int,
|
||||
id: str,
|
||||
quote_id: str,
|
||||
split: Optional[List[int]] = None,
|
||||
) -> List[Proof]:
|
||||
"""Mint tokens of a specific amount after an invoice has been paid.
|
||||
@@ -553,7 +522,7 @@ class Wallet(
|
||||
outputs, rs = self._construct_outputs(amounts, secrets, rs)
|
||||
|
||||
# will raise exception if mint is unsuccessful
|
||||
promises = await super().mint(outputs, id)
|
||||
promises = await super().mint(outputs, quote_id)
|
||||
|
||||
promises_keyset_id = promises[0].id
|
||||
await bump_secret_derivation(
|
||||
@@ -561,15 +530,17 @@ class Wallet(
|
||||
)
|
||||
proofs = await self._construct_proofs(promises, secrets, rs, derivation_paths)
|
||||
|
||||
if id:
|
||||
await update_lightning_invoice(
|
||||
db=self.db, id=id, paid=True, time_paid=int(time.time())
|
||||
await update_bolt11_mint_quote(
|
||||
db=self.db,
|
||||
quote=quote_id,
|
||||
state=MintQuoteState.paid,
|
||||
paid_time=int(time.time()),
|
||||
)
|
||||
# store the mint_id in proofs
|
||||
async with self.db.connect() as conn:
|
||||
for p in proofs:
|
||||
p.mint_id = id
|
||||
await update_proof(p, mint_id=id, conn=conn)
|
||||
p.mint_id = quote_id
|
||||
await update_proof(p, mint_id=quote_id, conn=conn)
|
||||
return proofs
|
||||
|
||||
async def redeem(
|
||||
@@ -725,11 +696,19 @@ class Wallet(
|
||||
"""
|
||||
if amount and not self.mint_info.supports_mpp("bolt11", self.unit):
|
||||
raise Exception("Mint does not support MPP, cannot specify amount.")
|
||||
melt_quote = await super().melt_quote(invoice, self.unit, amount)
|
||||
melt_quote_resp = await super().melt_quote(invoice, self.unit, amount)
|
||||
logger.debug(
|
||||
f"Mint wants {self.unit.str(melt_quote.fee_reserve)} as fee reserve."
|
||||
f"Mint wants {self.unit.str(melt_quote_resp.fee_reserve)} as fee reserve."
|
||||
)
|
||||
return melt_quote
|
||||
melt_quote = MeltQuote.from_resp_wallet(
|
||||
melt_quote_resp,
|
||||
self.url,
|
||||
amount=melt_quote_resp.amount,
|
||||
unit=self.unit.name,
|
||||
request=invoice,
|
||||
)
|
||||
await store_bolt11_melt_quote(db=self.db, quote=melt_quote)
|
||||
return melt_quote_resp
|
||||
|
||||
async def melt(
|
||||
self, proofs: List[Proof], invoice: str, fee_reserve_sat: int, quote_id: str
|
||||
@@ -744,6 +723,7 @@ class Wallet(
|
||||
"""
|
||||
# Make sure we're operating on an independent copy of proofs
|
||||
proofs = copy.copy(proofs)
|
||||
amount = sum_proofs(proofs)
|
||||
|
||||
# Generate a number of blank outputs for any overpaid fees. As described in
|
||||
# NUT-08, the mint will imprint these outputs with a value depending on the
|
||||
@@ -764,59 +744,56 @@ class Wallet(
|
||||
p.melt_id = quote_id
|
||||
await update_proof(p, melt_id=quote_id, conn=conn)
|
||||
|
||||
# we store the invoice object in the database to later be able to check the invoice state
|
||||
|
||||
decoded_invoice = bolt11.decode(invoice)
|
||||
invoice_obj = Invoice(
|
||||
amount=-sum_proofs(proofs),
|
||||
bolt11=invoice,
|
||||
payment_hash=decoded_invoice.payment_hash,
|
||||
# preimage=status.preimage,
|
||||
paid=False,
|
||||
time_paid=int(time.time()),
|
||||
id=quote_id, # store the same ID in the invoice
|
||||
out=True, # outgoing invoice
|
||||
melt_quote_resp = await super().melt(quote_id, proofs, change_outputs)
|
||||
melt_quote = MeltQuote.from_resp_wallet(
|
||||
melt_quote_resp,
|
||||
self.url,
|
||||
amount=amount,
|
||||
unit=self.unit.name,
|
||||
request=invoice,
|
||||
)
|
||||
# store invoice in db as not paid yet
|
||||
await store_lightning_invoice(db=self.db, invoice=invoice_obj)
|
||||
|
||||
status = await super().melt(quote_id, proofs, change_outputs)
|
||||
|
||||
# if payment fails
|
||||
if MeltQuoteState(status.state) == MeltQuoteState.unpaid:
|
||||
if melt_quote.state == MeltQuoteState.unpaid:
|
||||
# remove the melt_id in proofs and set reserved to False
|
||||
for p in proofs:
|
||||
p.melt_id = None
|
||||
p.reserved = False
|
||||
await update_proof(p, melt_id="", db=self.db)
|
||||
raise Exception("could not pay invoice.")
|
||||
elif MeltQuoteState(status.state) == MeltQuoteState.pending:
|
||||
elif melt_quote.state == MeltQuoteState.pending:
|
||||
# payment is still pending
|
||||
return status
|
||||
logger.debug("Payment is still pending.")
|
||||
return melt_quote_resp
|
||||
|
||||
# invoice was paid successfully
|
||||
await self.invalidate(proofs)
|
||||
|
||||
# update paid status in db
|
||||
logger.trace(f"Settings invoice {quote_id} to paid.")
|
||||
await update_lightning_invoice(
|
||||
logger.trace(f"Quote: {melt_quote_resp}")
|
||||
fee_paid = melt_quote.amount + melt_quote.fee_paid
|
||||
if melt_quote.change:
|
||||
fee_paid -= sum_promises(melt_quote.change)
|
||||
|
||||
await update_bolt11_melt_quote(
|
||||
db=self.db,
|
||||
id=quote_id,
|
||||
paid=True,
|
||||
time_paid=int(time.time()),
|
||||
preimage=status.payment_preimage,
|
||||
quote=quote_id,
|
||||
state=MeltQuoteState.paid,
|
||||
paid_time=int(time.time()),
|
||||
payment_preimage=melt_quote.payment_preimage or "",
|
||||
fee_paid=fee_paid,
|
||||
)
|
||||
|
||||
# handle change and produce proofs
|
||||
if status.change:
|
||||
if melt_quote.change:
|
||||
change_proofs = await self._construct_proofs(
|
||||
status.change,
|
||||
change_secrets[: len(status.change)],
|
||||
change_rs[: len(status.change)],
|
||||
change_derivation_paths[: len(status.change)],
|
||||
melt_quote.change,
|
||||
change_secrets[: len(melt_quote.change)],
|
||||
change_rs[: len(melt_quote.change)],
|
||||
change_derivation_paths[: len(melt_quote.change)],
|
||||
)
|
||||
logger.debug(f"Received change: {self.unit.str(sum_proofs(change_proofs))}")
|
||||
return status
|
||||
return melt_quote_resp
|
||||
|
||||
async def check_proof_state(self, proofs) -> PostCheckStateResponse:
|
||||
return await super().check_proof_state(proofs)
|
||||
|
||||
@@ -63,7 +63,7 @@ async def test_db_tables(ledger: Ledger):
|
||||
"SELECT table_name FROM information_schema.tables WHERE table_schema ="
|
||||
" 'public';"
|
||||
)
|
||||
tables_all: List[Tuple[str]] = tables_res.all()
|
||||
tables_all: List[Tuple[str]] = tables_res.all() # type: ignore
|
||||
tables = [t[0] for t in tables_all]
|
||||
tables_expected = [
|
||||
"dbversions",
|
||||
@@ -117,7 +117,7 @@ async def test_db_get_connection(ledger: Ledger):
|
||||
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_db_get_connection_locked(wallet: Wallet, ledger: Ledger):
|
||||
# invoice = await wallet.request_mint(64)
|
||||
# mint_quote = await wallet.request_mint(64)
|
||||
|
||||
# async def get_connection():
|
||||
# """This code makes sure that only the error of the second connection is raised (which we check in the assert_err)"""
|
||||
@@ -129,7 +129,7 @@ async def test_db_get_connection(ledger: Ledger):
|
||||
# ) as conn2:
|
||||
# # write something with conn1, we never reach this point if the lock works
|
||||
# await conn2.execute(
|
||||
# f"INSERT INTO mint_quotes (quote, amount) VALUES ('{invoice.id}', 100);"
|
||||
# f"INSERT INTO mint_quotes (quote, amount) VALUES ('{mint_quote.quote}', 100);"
|
||||
# )
|
||||
# except Exception as exc:
|
||||
# # this is expected to raise
|
||||
@@ -149,28 +149,28 @@ async def test_db_get_connection_lock_row(wallet: Wallet, ledger: Ledger):
|
||||
if ledger.db.type == db.SQLITE:
|
||||
pytest.skip("SQLite does not support row locking")
|
||||
|
||||
invoice = await wallet.request_mint(64)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
|
||||
async def get_connection():
|
||||
"""This code makes sure that only the error of the second connection is raised (which we check in the assert_err)"""
|
||||
try:
|
||||
async with ledger.db.get_connection(
|
||||
lock_table="mint_quotes",
|
||||
lock_select_statement=f"quote='{invoice.id}'",
|
||||
lock_select_statement=f"quote='{mint_quote.quote}'",
|
||||
lock_timeout=0.1,
|
||||
) as conn1:
|
||||
await conn1.execute(
|
||||
f"UPDATE mint_quotes SET amount=100 WHERE quote='{invoice.id}';"
|
||||
f"UPDATE mint_quotes SET amount=100 WHERE quote='{mint_quote.quote}';"
|
||||
)
|
||||
try:
|
||||
async with ledger.db.get_connection(
|
||||
lock_table="mint_quotes",
|
||||
lock_select_statement=f"quote='{invoice.id}'",
|
||||
lock_select_statement=f"quote='{mint_quote.quote}'",
|
||||
lock_timeout=0.1,
|
||||
) as conn2:
|
||||
# write something with conn1, we never reach this point if the lock works
|
||||
await conn2.execute(
|
||||
f"UPDATE mint_quotes SET amount=101 WHERE quote='{invoice.id}';"
|
||||
f"UPDATE mint_quotes SET amount=101 WHERE quote='{mint_quote.quote}';"
|
||||
)
|
||||
except Exception as exc:
|
||||
# this is expected to raise
|
||||
@@ -189,9 +189,9 @@ async def test_db_verify_spent_proofs_and_set_pending_race_condition(
|
||||
wallet: Wallet, ledger: Ledger
|
||||
):
|
||||
# fill wallet
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
|
||||
await assert_err_multiple(
|
||||
@@ -211,9 +211,9 @@ async def test_db_verify_spent_proofs_and_set_pending_delayed_no_race_condition(
|
||||
wallet: Wallet, ledger: Ledger
|
||||
):
|
||||
# fill wallet
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
|
||||
async def delayed_verify_spent_proofs_and_set_pending():
|
||||
@@ -234,9 +234,9 @@ async def test_db_verify_spent_proofs_and_set_pending_no_race_condition_differen
|
||||
wallet: Wallet, ledger: Ledger
|
||||
):
|
||||
# fill wallet
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id, split=[32, 32])
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote, split=[32, 32])
|
||||
assert wallet.balance == 64
|
||||
assert len(wallet.proofs) == 2
|
||||
|
||||
@@ -251,26 +251,26 @@ async def test_db_get_connection_lock_different_row(wallet: Wallet, ledger: Ledg
|
||||
if ledger.db.type == db.SQLITE:
|
||||
pytest.skip("SQLite does not support row locking")
|
||||
# this should work since we lock two different rows
|
||||
invoice = await wallet.request_mint(64)
|
||||
invoice2 = await wallet.request_mint(64)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
mint_quote_2 = await wallet.request_mint(64)
|
||||
|
||||
async def get_connection2():
|
||||
"""This code makes sure that only the error of the second connection is raised (which we check in the assert_err)"""
|
||||
try:
|
||||
async with ledger.db.get_connection(
|
||||
lock_table="mint_quotes",
|
||||
lock_select_statement=f"quote='{invoice.id}'",
|
||||
lock_select_statement=f"quote='{mint_quote.quote}'",
|
||||
lock_timeout=0.1,
|
||||
):
|
||||
try:
|
||||
async with ledger.db.get_connection(
|
||||
lock_table="mint_quotes",
|
||||
lock_select_statement=f"quote='{invoice2.id}'",
|
||||
lock_select_statement=f"quote='{mint_quote_2.quote}'",
|
||||
lock_timeout=0.1,
|
||||
) as conn2:
|
||||
# write something with conn1, this time we should reach this block with postgres
|
||||
quote = await ledger.crud.get_mint_quote(
|
||||
quote_id=invoice2.id, db=ledger.db, conn=conn2
|
||||
quote_id=mint_quote_2.quote, db=ledger.db, conn=conn2
|
||||
)
|
||||
assert quote is not None
|
||||
quote.amount = 100
|
||||
@@ -294,10 +294,10 @@ async def test_db_get_connection_lock_different_row(wallet: Wallet, ledger: Ledg
|
||||
@pytest.mark.asyncio
|
||||
async def test_db_lock_table(wallet: Wallet, ledger: Ledger):
|
||||
# fill wallet
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
|
||||
async with ledger.db.connect(lock_table="proofs_pending", lock_timeout=0.1) as conn:
|
||||
|
||||
@@ -159,9 +159,9 @@ async def test_api_keyset_keys_old_keyset_id(ledger: Ledger):
|
||||
reason="settings.debug_mint_only_deprecated is set",
|
||||
)
|
||||
async def test_split(ledger: Ledger, wallet: Wallet):
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
secrets, rs, derivation_paths = await wallet.generate_n_secrets(2)
|
||||
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
|
||||
@@ -240,15 +240,14 @@ async def test_mint_quote(ledger: Ledger):
|
||||
reason="settings.debug_mint_only_deprecated is set",
|
||||
)
|
||||
async def test_mint(ledger: Ledger, wallet: Wallet):
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
quote_id = invoice.id
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(10000, 10001)
|
||||
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
|
||||
outputs_payload = [o.dict() for o in outputs]
|
||||
response = httpx.post(
|
||||
f"{BASE_URL}/v1/mint/bolt11",
|
||||
json={"quote": quote_id, "outputs": outputs_payload},
|
||||
json={"quote": mint_quote.quote, "outputs": outputs_payload},
|
||||
timeout=None,
|
||||
)
|
||||
assert response.status_code == 200, f"{response.url} {response.status_code}"
|
||||
@@ -273,8 +272,8 @@ async def test_mint(ledger: Ledger, wallet: Wallet):
|
||||
)
|
||||
async def test_melt_quote_internal(ledger: Ledger, wallet: Wallet):
|
||||
# internal invoice
|
||||
invoice = await wallet.request_mint(64)
|
||||
request = invoice.bolt11
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
request = mint_quote.request
|
||||
response = httpx.post(
|
||||
f"{BASE_URL}/v1/melt/quote/bolt11",
|
||||
json={"unit": "sat", "request": request},
|
||||
@@ -358,14 +357,14 @@ async def test_melt_quote_external(ledger: Ledger, wallet: Wallet):
|
||||
)
|
||||
async def test_melt_internal(ledger: Ledger, wallet: Wallet):
|
||||
# internal invoice
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
|
||||
# create invoice to melt to
|
||||
invoice = await wallet.request_mint(64)
|
||||
invoice_payment_request = invoice.bolt11
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
invoice_payment_request = mint_quote.request
|
||||
|
||||
quote = await wallet.melt_quote(invoice_payment_request)
|
||||
assert quote.amount == 64
|
||||
@@ -389,7 +388,7 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet):
|
||||
)
|
||||
assert response.status_code == 200, f"{response.url} {response.status_code}"
|
||||
result = response.json()
|
||||
assert result.get("payment_preimage") is not None
|
||||
assert result.get("payment_preimage") is None
|
||||
assert result["paid"] is True
|
||||
|
||||
# deserialize the response
|
||||
@@ -397,7 +396,7 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet):
|
||||
assert resp_quote.quote == quote.quote
|
||||
|
||||
# internal invoice, no preimage, no change
|
||||
assert resp_quote.payment_preimage == ""
|
||||
assert resp_quote.payment_preimage is None
|
||||
assert resp_quote.change == []
|
||||
assert resp_quote.state == MeltQuoteState.paid.value
|
||||
|
||||
@@ -417,9 +416,9 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet):
|
||||
)
|
||||
async def test_melt_external(ledger: Ledger, wallet: Wallet):
|
||||
# internal invoice
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
|
||||
invoice_dict = get_real_invoice(62)
|
||||
@@ -493,9 +492,9 @@ async def test_api_check_state(ledger: Ledger):
|
||||
reason="settings.debug_mint_only_deprecated is set",
|
||||
)
|
||||
async def test_api_restore(ledger: Ledger, wallet: Wallet):
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
secret_counter = await bump_secret_derivation(
|
||||
db=wallet.db, keyset_id=wallet.keyset_id, by=0, skip=True
|
||||
|
||||
@@ -67,9 +67,9 @@ async def test_api_keyset_keys(ledger: Ledger):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_split(ledger: Ledger, wallet: Wallet):
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(20000, 20001)
|
||||
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
|
||||
@@ -88,9 +88,9 @@ async def test_split(ledger: Ledger, wallet: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_split_deprecated_with_amount(ledger: Ledger, wallet: Wallet):
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(80000, 80001)
|
||||
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
|
||||
@@ -124,16 +124,15 @@ async def test_api_mint_validation(ledger):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mint(ledger: Ledger, wallet: Wallet):
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
quote_id = invoice.id
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(10000, 10001)
|
||||
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
|
||||
outputs_payload = [o.dict() for o in outputs]
|
||||
response = httpx.post(
|
||||
f"{BASE_URL}/mint",
|
||||
json={"outputs": outputs_payload},
|
||||
params={"hash": quote_id},
|
||||
params={"hash": mint_quote.quote},
|
||||
timeout=None,
|
||||
)
|
||||
assert response.status_code == 200, f"{response.url} {response.status_code}"
|
||||
@@ -150,15 +149,15 @@ async def test_mint(ledger: Ledger, wallet: Wallet):
|
||||
@pytest.mark.asyncio
|
||||
async def test_melt_internal(ledger: Ledger, wallet: Wallet):
|
||||
# fill wallet
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
|
||||
# create invoice to melt to
|
||||
invoice = await wallet.request_mint(64)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
|
||||
invoice_payment_request = invoice.bolt11
|
||||
invoice_payment_request = mint_quote.request
|
||||
|
||||
quote = await wallet.melt_quote(invoice_payment_request)
|
||||
assert quote.amount == 64
|
||||
@@ -182,7 +181,7 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet):
|
||||
)
|
||||
assert response.status_code == 200, f"{response.url} {response.status_code}"
|
||||
result = response.json()
|
||||
assert result.get("preimage") is not None
|
||||
assert result.get("preimage") is None
|
||||
assert result["paid"] is True
|
||||
|
||||
|
||||
@@ -190,14 +189,14 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet):
|
||||
async def test_melt_internal_no_change_outputs(ledger: Ledger, wallet: Wallet):
|
||||
# Clients without NUT-08 will not send change outputs
|
||||
# internal invoice
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
|
||||
# create invoice to melt to
|
||||
invoice = await wallet.request_mint(64)
|
||||
invoice_payment_request = invoice.bolt11
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
invoice_payment_request = mint_quote.request
|
||||
quote = await wallet.melt_quote(invoice_payment_request)
|
||||
assert quote.amount == 64
|
||||
assert quote.fee_reserve == 0
|
||||
@@ -218,7 +217,7 @@ async def test_melt_internal_no_change_outputs(ledger: Ledger, wallet: Wallet):
|
||||
)
|
||||
assert response.status_code == 200, f"{response.url} {response.status_code}"
|
||||
result = response.json()
|
||||
assert result.get("preimage") is not None
|
||||
assert result.get("preimage") is None
|
||||
assert result["paid"] is True
|
||||
|
||||
|
||||
@@ -229,9 +228,9 @@ async def test_melt_internal_no_change_outputs(ledger: Ledger, wallet: Wallet):
|
||||
)
|
||||
async def test_melt_external(ledger: Ledger, wallet: Wallet):
|
||||
# internal invoice
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
|
||||
# create invoice to melt to
|
||||
@@ -271,11 +270,11 @@ async def test_melt_external(ledger: Ledger, wallet: Wallet):
|
||||
@pytest.mark.asyncio
|
||||
async def test_checkfees(ledger: Ledger, wallet: Wallet):
|
||||
# internal invoice
|
||||
invoice = await wallet.request_mint(64)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
response = httpx.post(
|
||||
f"{BASE_URL}/checkfees",
|
||||
json={
|
||||
"pr": invoice.bolt11,
|
||||
"pr": mint_quote.request,
|
||||
},
|
||||
timeout=None,
|
||||
)
|
||||
@@ -323,9 +322,9 @@ async def test_api_check_state(ledger: Ledger):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_api_restore(ledger: Ledger, wallet: Wallet):
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
secret_counter = await bump_secret_derivation(
|
||||
db=wallet.db, keyset_id=wallet.keyset_id, by=0, skip=True
|
||||
|
||||
@@ -37,9 +37,9 @@ async def wallet(ledger: Ledger):
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.skipif(is_github_actions, reason="GITHUB_ACTIONS")
|
||||
async def test_mint_proofs_pending(wallet: Wallet, ledger: Ledger):
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
proofs = wallet.proofs.copy()
|
||||
|
||||
proofs_states_before_split = await wallet.check_proof_state(proofs)
|
||||
@@ -61,26 +61,21 @@ async def test_mint_proofs_pending(wallet: Wallet, ledger: Ledger):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mint_quote(wallet: Wallet, ledger: Ledger):
|
||||
invoice = await wallet.request_mint(128)
|
||||
assert invoice is not None
|
||||
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
|
||||
mint_quote = await wallet.request_mint(128)
|
||||
quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db)
|
||||
assert quote is not None
|
||||
assert quote.quote == invoice.id
|
||||
assert quote.amount == 128
|
||||
assert quote.unit == "sat"
|
||||
assert not quote.paid
|
||||
assert quote.checking_id == invoice.payment_hash
|
||||
# assert quote.paid_time is None
|
||||
assert quote.created_time
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mint_quote_state_transitions(wallet: Wallet, ledger: Ledger):
|
||||
invoice = await wallet.request_mint(128)
|
||||
assert invoice is not None
|
||||
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
|
||||
mint_quote = await wallet.request_mint(128)
|
||||
quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db)
|
||||
assert quote is not None
|
||||
assert quote.quote == invoice.id
|
||||
assert quote.unpaid
|
||||
|
||||
# set pending again
|
||||
@@ -129,11 +124,9 @@ async def test_mint_quote_state_transitions(wallet: Wallet, ledger: Ledger):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_mint_quote_by_request(wallet: Wallet, ledger: Ledger):
|
||||
invoice = await wallet.request_mint(128)
|
||||
assert invoice is not None
|
||||
quote = await ledger.crud.get_mint_quote(request=invoice.bolt11, db=ledger.db)
|
||||
mint_quote = await wallet.request_mint(128)
|
||||
quote = await ledger.crud.get_mint_quote(request=mint_quote.request, db=ledger.db)
|
||||
assert quote is not None
|
||||
assert quote.quote == invoice.id
|
||||
assert quote.amount == 128
|
||||
assert quote.unit == "sat"
|
||||
assert not quote.paid
|
||||
@@ -143,10 +136,9 @@ async def test_get_mint_quote_by_request(wallet: Wallet, ledger: Ledger):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_melt_quote(wallet: Wallet, ledger: Ledger):
|
||||
invoice = await wallet.request_mint(128)
|
||||
assert invoice is not None
|
||||
mint_quote = await wallet.request_mint(128)
|
||||
melt_quote = await ledger.melt_quote(
|
||||
PostMeltQuoteRequest(request=invoice.bolt11, unit="sat")
|
||||
PostMeltQuoteRequest(request=mint_quote.request, unit="sat")
|
||||
)
|
||||
quote = await ledger.crud.get_melt_quote(quote_id=melt_quote.quote, db=ledger.db)
|
||||
assert quote is not None
|
||||
@@ -154,17 +146,15 @@ async def test_melt_quote(wallet: Wallet, ledger: Ledger):
|
||||
assert quote.amount == 128
|
||||
assert quote.unit == "sat"
|
||||
assert not quote.paid
|
||||
assert quote.checking_id == invoice.payment_hash
|
||||
# assert quote.paid_time is None
|
||||
assert quote.created_time
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_melt_quote_set_pending(wallet: Wallet, ledger: Ledger):
|
||||
invoice = await wallet.request_mint(128)
|
||||
assert invoice is not None
|
||||
mint_quote = await wallet.request_mint(128)
|
||||
melt_quote = await ledger.melt_quote(
|
||||
PostMeltQuoteRequest(request=invoice.bolt11, unit="sat")
|
||||
PostMeltQuoteRequest(request=mint_quote.request, unit="sat")
|
||||
)
|
||||
assert melt_quote is not None
|
||||
assert melt_quote.state == MeltQuoteState.unpaid.value
|
||||
@@ -187,10 +177,9 @@ async def test_melt_quote_set_pending(wallet: Wallet, ledger: Ledger):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_melt_quote_state_transitions(wallet: Wallet, ledger: Ledger):
|
||||
invoice = await wallet.request_mint(128)
|
||||
assert invoice is not None
|
||||
mint_quote = await wallet.request_mint(128)
|
||||
melt_quote = await ledger.melt_quote(
|
||||
PostMeltQuoteRequest(request=invoice.bolt11, unit="sat")
|
||||
PostMeltQuoteRequest(request=mint_quote.request, unit="sat")
|
||||
)
|
||||
quote = await ledger.crud.get_melt_quote(quote_id=melt_quote.quote, db=ledger.db)
|
||||
assert quote is not None
|
||||
@@ -218,33 +207,36 @@ async def test_melt_quote_state_transitions(wallet: Wallet, ledger: Ledger):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mint_quote_set_pending(wallet: Wallet, ledger: Ledger):
|
||||
invoice = await wallet.request_mint(128)
|
||||
assert invoice is not None
|
||||
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
|
||||
assert quote is not None
|
||||
assert quote.unpaid
|
||||
mint_quote = await wallet.request_mint(128)
|
||||
mint_quote = await ledger.crud.get_mint_quote(
|
||||
quote_id=mint_quote.quote, db=ledger.db
|
||||
)
|
||||
assert mint_quote is not None
|
||||
assert mint_quote.unpaid
|
||||
|
||||
# pay_if_regtest pays on regtest, get_mint_quote pays on FakeWallet
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
_ = await ledger.get_mint_quote(invoice.id)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
_ = await ledger.get_mint_quote(mint_quote.quote)
|
||||
|
||||
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
|
||||
quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db)
|
||||
assert quote is not None
|
||||
assert quote.paid
|
||||
|
||||
previous_state = MintQuoteState.paid
|
||||
await ledger.db_write._set_mint_quote_pending(quote.quote)
|
||||
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
|
||||
quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db)
|
||||
assert quote is not None
|
||||
assert quote.pending
|
||||
|
||||
# try to mint while pending
|
||||
await assert_err(wallet.mint(128, id=invoice.id), "Mint quote already pending.")
|
||||
await assert_err(
|
||||
wallet.mint(128, quote_id=mint_quote.quote), "Mint quote already pending."
|
||||
)
|
||||
|
||||
# set unpending
|
||||
await ledger.db_write._unset_mint_quote_pending(quote.quote, previous_state)
|
||||
|
||||
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
|
||||
quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db)
|
||||
assert quote is not None
|
||||
assert quote.state == previous_state
|
||||
assert quote.paid
|
||||
@@ -253,20 +245,19 @@ async def test_mint_quote_set_pending(wallet: Wallet, ledger: Ledger):
|
||||
# quote.state = MintQuoteState.paid
|
||||
# await ledger.crud.update_mint_quote(quote=quote, db=ledger.db)
|
||||
|
||||
await wallet.mint(quote.amount, id=quote.quote)
|
||||
await wallet.mint(quote.amount, quote_id=quote.quote)
|
||||
|
||||
# check if quote is issued
|
||||
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
|
||||
quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db)
|
||||
assert quote is not None
|
||||
assert quote.issued
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_db_events_add_client(wallet: Wallet, ledger: Ledger):
|
||||
invoice = await wallet.request_mint(128)
|
||||
assert invoice is not None
|
||||
mint_quote = await wallet.request_mint(128)
|
||||
melt_quote = await ledger.melt_quote(
|
||||
PostMeltQuoteRequest(request=invoice.bolt11, unit="sat")
|
||||
PostMeltQuoteRequest(request=mint_quote.request, unit="sat")
|
||||
)
|
||||
assert melt_quote is not None
|
||||
assert melt_quote.state == MeltQuoteState.unpaid.value
|
||||
|
||||
@@ -48,9 +48,9 @@ def set_ledger_keyset_fees(
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_fees_for_proofs(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, split=[1] * 64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, split=[1] * 64, quote_id=mint_quote.quote)
|
||||
|
||||
# two proofs
|
||||
|
||||
@@ -105,9 +105,9 @@ async def test_wallet_selection_with_fee(wallet1: Wallet, ledger: Ledger):
|
||||
for keyset in wallet1.keysets.values():
|
||||
assert keyset.input_fee_ppk == 100
|
||||
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
|
||||
send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10)
|
||||
assert sum_proofs(send_proofs) == 10
|
||||
@@ -123,9 +123,11 @@ async def test_wallet_selection_with_fee(wallet1: Wallet, ledger: Ledger):
|
||||
async def test_wallet_swap_to_send_with_fee(wallet1: Wallet, ledger: Ledger):
|
||||
# set fees to 100 ppk
|
||||
set_ledger_keyset_fees(100, ledger, wallet1)
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id, split=[32, 32]) # make sure we need to swap
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(
|
||||
64, quote_id=mint_quote.quote, split=[32, 32]
|
||||
) # make sure we need to swap
|
||||
|
||||
# quirk: this should call a `/v1/swap` with the mint but the mint will
|
||||
# throw an error since the fees are only changed in the `ledger` instance, not in the uvicorn API server
|
||||
@@ -142,9 +144,9 @@ async def test_wallet_swap_to_send_with_fee(wallet1: Wallet, ledger: Ledger):
|
||||
async def test_split_with_fees(wallet1: Wallet, ledger: Ledger):
|
||||
# set fees to 100 ppk
|
||||
set_ledger_keyset_fees(100, ledger)
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
|
||||
send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10)
|
||||
fees = ledger.get_fees_for_proofs(send_proofs)
|
||||
@@ -160,9 +162,9 @@ async def test_split_with_fees(wallet1: Wallet, ledger: Ledger):
|
||||
async def test_split_with_high_fees(wallet1: Wallet, ledger: Ledger):
|
||||
# set fees to 100 ppk
|
||||
set_ledger_keyset_fees(1234, ledger)
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
|
||||
send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10)
|
||||
fees = ledger.get_fees_for_proofs(send_proofs)
|
||||
@@ -178,9 +180,9 @@ async def test_split_with_high_fees(wallet1: Wallet, ledger: Ledger):
|
||||
async def test_split_not_enough_fees(wallet1: Wallet, ledger: Ledger):
|
||||
# set fees to 100 ppk
|
||||
set_ledger_keyset_fees(100, ledger)
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
|
||||
send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10)
|
||||
fees = ledger.get_fees_for_proofs(send_proofs)
|
||||
@@ -200,14 +202,14 @@ async def test_melt_internal(wallet1: Wallet, ledger: Ledger):
|
||||
set_ledger_keyset_fees(100, ledger, wallet1)
|
||||
|
||||
# mint twice so we have enough to pay the second invoice back
|
||||
invoice = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(128, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(128, quote_id=mint_quote.quote)
|
||||
assert wallet1.balance == 128
|
||||
|
||||
# create a mint quote so that we can melt to it internally
|
||||
invoice_to_pay = await wallet1.request_mint(64)
|
||||
invoice_payment_request = invoice_to_pay.bolt11
|
||||
invoice_payment_request = invoice_to_pay.request
|
||||
|
||||
melt_quote = await ledger.melt_quote(
|
||||
PostMeltQuoteRequest(request=invoice_payment_request, unit="sat")
|
||||
@@ -247,9 +249,9 @@ async def test_melt_external_with_fees(wallet1: Wallet, ledger: Ledger):
|
||||
set_ledger_keyset_fees(100, ledger, wallet1)
|
||||
|
||||
# mint twice so we have enough to pay the second invoice back
|
||||
invoice = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(128, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(128, quote_id=mint_quote.quote)
|
||||
assert wallet1.balance == 128
|
||||
|
||||
invoice_dict = get_real_invoice(64)
|
||||
|
||||
@@ -261,9 +261,9 @@ async def test_startup_fakewallet_pending_quote_unknown(ledger: Ledger):
|
||||
@pytest.mark.skipif(is_fake, reason="only regtest")
|
||||
async def test_startup_regtest_pending_quote_pending(wallet: Wallet, ledger: Ledger):
|
||||
# fill wallet
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
|
||||
# create hodl invoice
|
||||
@@ -305,9 +305,9 @@ async def test_startup_regtest_pending_quote_pending(wallet: Wallet, ledger: Led
|
||||
@pytest.mark.skipif(is_fake, reason="only regtest")
|
||||
async def test_startup_regtest_pending_quote_success(wallet: Wallet, ledger: Ledger):
|
||||
# fill wallet
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
|
||||
# create hodl invoice
|
||||
@@ -353,9 +353,9 @@ async def test_startup_regtest_pending_quote_success(wallet: Wallet, ledger: Led
|
||||
async def test_startup_regtest_pending_quote_failure(wallet: Wallet, ledger: Ledger):
|
||||
"""Simulate a failure to pay the hodl invoice by canceling it."""
|
||||
# fill wallet
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
|
||||
# create hodl invoice
|
||||
@@ -407,9 +407,9 @@ async def test_startup_regtest_pending_quote_unknown(wallet: Wallet, ledger: Led
|
||||
points to an unknown payment."""
|
||||
|
||||
# fill wallet
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
|
||||
# create hodl invoice
|
||||
|
||||
@@ -185,9 +185,9 @@ async def test_fakewallet_pending_quote_get_melt_quote_unknown(ledger: Ledger):
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.skipif(is_regtest, reason="only fake wallet")
|
||||
async def test_melt_lightning_pay_invoice_settled(ledger: Ledger, wallet: Wallet):
|
||||
invoice = await wallet.request_mint(64)
|
||||
await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
# invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0"
|
||||
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
|
||||
quote_id = (
|
||||
@@ -205,9 +205,9 @@ async def test_melt_lightning_pay_invoice_settled(ledger: Ledger, wallet: Wallet
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.skipif(is_regtest, reason="only fake wallet")
|
||||
async def test_melt_lightning_pay_invoice_failed_failed(ledger: Ledger, wallet: Wallet):
|
||||
invoice = await wallet.request_mint(64)
|
||||
await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
# invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0"
|
||||
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
|
||||
quote_id = (
|
||||
@@ -254,9 +254,9 @@ async def test_melt_lightning_pay_invoice_failed_failed(ledger: Ledger, wallet:
|
||||
async def test_melt_lightning_pay_invoice_failed_settled(
|
||||
ledger: Ledger, wallet: Wallet
|
||||
):
|
||||
invoice = await wallet.request_mint(64)
|
||||
await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
|
||||
quote_id = (
|
||||
await ledger.melt_quote(
|
||||
@@ -278,9 +278,9 @@ async def test_melt_lightning_pay_invoice_failed_settled(
|
||||
async def test_melt_lightning_pay_invoice_failed_pending(
|
||||
ledger: Ledger, wallet: Wallet
|
||||
):
|
||||
invoice = await wallet.request_mint(64)
|
||||
await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
|
||||
quote_id = (
|
||||
await ledger.melt_quote(
|
||||
@@ -303,9 +303,9 @@ async def test_melt_lightning_pay_invoice_exception_exception(
|
||||
ledger: Ledger, wallet: Wallet
|
||||
):
|
||||
"""Simulates the case where pay_invoice and get_payment_status raise an exception (due to network issues for example)."""
|
||||
invoice = await wallet.request_mint(64)
|
||||
await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
# invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0"
|
||||
invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8"
|
||||
quote_id = (
|
||||
@@ -338,8 +338,8 @@ async def test_melt_lightning_pay_invoice_exception_exception(
|
||||
async def test_mint_melt_different_units(ledger: Ledger, wallet: Wallet):
|
||||
"""Mint and melt different units."""
|
||||
# load the wallet
|
||||
invoice = await wallet.request_mint(64)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
|
||||
amount = 32
|
||||
|
||||
|
||||
@@ -38,14 +38,14 @@ async def wallet1(ledger: Ledger):
|
||||
@pytest.mark.skipif(is_regtest, reason="only works with FakeWallet")
|
||||
async def test_melt_internal(wallet1: Wallet, ledger: Ledger):
|
||||
# mint twice so we have enough to pay the second invoice back
|
||||
invoice = await wallet1.request_mint(128)
|
||||
await ledger.get_mint_quote(invoice.id)
|
||||
await wallet1.mint(128, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(128)
|
||||
await ledger.get_mint_quote(mint_quote.quote)
|
||||
await wallet1.mint(128, quote_id=mint_quote.quote)
|
||||
assert wallet1.balance == 128
|
||||
|
||||
# create a mint quote so that we can melt to it internally
|
||||
invoice_to_pay = await wallet1.request_mint(64)
|
||||
invoice_payment_request = invoice_to_pay.bolt11
|
||||
mint_quote_to_pay = await wallet1.request_mint(64)
|
||||
invoice_payment_request = mint_quote_to_pay.request
|
||||
|
||||
melt_quote = await ledger.melt_quote(
|
||||
PostMeltQuoteRequest(request=invoice_payment_request, unit="sat")
|
||||
@@ -79,9 +79,9 @@ async def test_melt_internal(wallet1: Wallet, ledger: Ledger):
|
||||
@pytest.mark.skipif(is_fake, reason="only works with Regtest")
|
||||
async def test_melt_external(wallet1: Wallet, ledger: Ledger):
|
||||
# mint twice so we have enough to pay the second invoice back
|
||||
invoice = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(128, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(128, quote_id=mint_quote.quote)
|
||||
assert wallet1.balance == 128
|
||||
|
||||
invoice_dict = get_real_invoice(64)
|
||||
@@ -119,14 +119,14 @@ async def test_melt_external(wallet1: Wallet, ledger: Ledger):
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.skipif(is_regtest, reason="only works with FakeWallet")
|
||||
async def test_mint_internal(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(128)
|
||||
await ledger.get_mint_quote(invoice.id)
|
||||
mint_quote = await ledger.get_mint_quote(invoice.id)
|
||||
mint_quote = await wallet1.request_mint(128)
|
||||
await ledger.get_mint_quote(mint_quote.quote)
|
||||
mint_quote = await ledger.get_mint_quote(mint_quote.quote)
|
||||
|
||||
assert mint_quote.paid, "mint quote should be paid"
|
||||
|
||||
if not settings.debug_mint_only_deprecated:
|
||||
mint_quote_resp = await wallet1.get_mint_quote(invoice.id)
|
||||
mint_quote_resp = await wallet1.get_mint_quote(mint_quote.quote)
|
||||
assert (
|
||||
mint_quote_resp.state == MeltQuoteState.paid.value
|
||||
), "mint quote should be paid"
|
||||
@@ -136,14 +136,14 @@ async def test_mint_internal(wallet1: Wallet, ledger: Ledger):
|
||||
len(output_amounts)
|
||||
)
|
||||
outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs)
|
||||
await ledger.mint(outputs=outputs, quote_id=invoice.id)
|
||||
await ledger.mint(outputs=outputs, quote_id=mint_quote.quote)
|
||||
|
||||
await assert_err(
|
||||
ledger.mint(outputs=outputs, quote_id=invoice.id),
|
||||
ledger.mint(outputs=outputs, quote_id=mint_quote.quote),
|
||||
"outputs have already been signed before.",
|
||||
)
|
||||
|
||||
mint_quote_after_payment = await ledger.get_mint_quote(invoice.id)
|
||||
mint_quote_after_payment = await ledger.get_mint_quote(mint_quote.quote)
|
||||
assert mint_quote_after_payment.issued, "mint quote should be issued"
|
||||
assert mint_quote_after_payment.issued
|
||||
|
||||
@@ -164,7 +164,7 @@ async def test_mint_external(wallet1: Wallet, ledger: Ledger):
|
||||
assert not mint_quote_resp.paid, "mint quote should not be paid"
|
||||
|
||||
await assert_err(
|
||||
wallet1.mint(128, id=quote.quote),
|
||||
wallet1.mint(128, quote_id=quote.quote),
|
||||
"quote not paid",
|
||||
)
|
||||
|
||||
@@ -187,9 +187,9 @@ async def test_mint_external(wallet1: Wallet, ledger: Ledger):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_split(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
|
||||
keep_proofs, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10)
|
||||
secrets, rs, derivation_paths = await wallet1.generate_n_secrets(len(send_proofs))
|
||||
@@ -204,9 +204,9 @@ async def test_split(wallet1: Wallet, ledger: Ledger):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_split_with_no_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
_, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10, set_reserved=False)
|
||||
await assert_err(
|
||||
ledger.swap(proofs=send_proofs, outputs=[]),
|
||||
@@ -216,9 +216,9 @@ async def test_split_with_no_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_split_with_input_less_than_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
|
||||
keep_proofs, send_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 10, set_reserved=False
|
||||
@@ -245,9 +245,9 @@ async def test_split_with_input_less_than_outputs(wallet1: Wallet, ledger: Ledge
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_split_with_input_more_than_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(128, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(128, quote_id=mint_quote.quote)
|
||||
|
||||
inputs = wallet1.proofs
|
||||
|
||||
@@ -269,9 +269,9 @@ async def test_split_with_input_more_than_outputs(wallet1: Wallet, ledger: Ledge
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_split_twice_with_same_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(128, split=[64, 64], id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(128, split=[64, 64], quote_id=mint_quote.quote)
|
||||
inputs1 = wallet1.proofs[:1]
|
||||
inputs2 = wallet1.proofs[1:]
|
||||
|
||||
@@ -304,30 +304,30 @@ async def test_split_twice_with_same_outputs(wallet1: Wallet, ledger: Ledger):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mint_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
mint_quote = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
output_amounts = [128]
|
||||
secrets, rs, derivation_paths = await wallet1.generate_n_secrets(
|
||||
len(output_amounts)
|
||||
)
|
||||
outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs)
|
||||
await ledger.mint(outputs=outputs, quote_id=invoice.id)
|
||||
await ledger.mint(outputs=outputs, quote_id=mint_quote.quote)
|
||||
|
||||
# now try to mint with the same outputs again
|
||||
invoice2 = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(invoice2.bolt11)
|
||||
mint_quote_2 = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(mint_quote_2.request)
|
||||
|
||||
await assert_err(
|
||||
ledger.mint(outputs=outputs, quote_id=invoice2.id),
|
||||
ledger.mint(outputs=outputs, quote_id=mint_quote_2.quote),
|
||||
"outputs have already been signed before.",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(130)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(130, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(130)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(130, quote_id=mint_quote.quote)
|
||||
|
||||
output_amounts = [128]
|
||||
secrets, rs, derivation_paths = await wallet1.generate_n_secrets(
|
||||
@@ -336,9 +336,9 @@ async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
|
||||
outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs)
|
||||
|
||||
# we use the outputs once for minting
|
||||
invoice2 = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(invoice2.bolt11)
|
||||
await ledger.mint(outputs=outputs, quote_id=invoice2.id)
|
||||
mint_quote_2 = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(mint_quote_2.request)
|
||||
await ledger.mint(outputs=outputs, quote_id=mint_quote_2.quote)
|
||||
|
||||
# use the same outputs for melting
|
||||
mint_quote = await ledger.mint_quote(PostMintQuoteRequest(unit="sat", amount=128))
|
||||
@@ -353,9 +353,9 @@ async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_melt_with_less_inputs_than_invoice(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(32)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(32, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(32)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(32, quote_id=mint_quote.quote)
|
||||
|
||||
# outputs for fee return
|
||||
output_amounts = [1, 1, 1, 1]
|
||||
@@ -382,9 +382,9 @@ async def test_melt_with_less_inputs_than_invoice(wallet1: Wallet, ledger: Ledge
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_melt_with_more_inputs_than_invoice(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(130)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(130, split=[64, 64, 2], id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(130)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(130, split=[64, 64, 2], quote_id=mint_quote.quote)
|
||||
|
||||
# outputs for fee return
|
||||
output_amounts = [1, 1, 1, 1]
|
||||
@@ -414,9 +414,9 @@ async def test_melt_with_more_inputs_than_invoice(wallet1: Wallet, ledger: Ledge
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_check_proof_state(wallet1: Wallet, ledger: Ledger):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
|
||||
keep_proofs, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10)
|
||||
|
||||
@@ -427,13 +427,13 @@ async def test_check_proof_state(wallet1: Wallet, ledger: Ledger):
|
||||
# TODO: test keeps running forever, needs to be fixed
|
||||
# @pytest.mark.asyncio
|
||||
# async def test_websocket_quote_updates(wallet1: Wallet, ledger: Ledger):
|
||||
# invoice = await wallet1.request_mint(64)
|
||||
# mint_quote = await wallet1.request_mint(64)
|
||||
# ws = websocket.create_connection(
|
||||
# f"ws://localhost:{SERVER_PORT}/v1/quote/{invoice.id}"
|
||||
# )
|
||||
# await asyncio.sleep(0.1)
|
||||
# await pay_if_regtest(invoice.bolt11)
|
||||
# await wallet1.mint(64, id=invoice.id)
|
||||
# await pay_if_regtest(mint_quote.request)
|
||||
# await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
# await asyncio.sleep(0.1)
|
||||
# data = str(ws.recv())
|
||||
# ws.close()
|
||||
|
||||
@@ -274,9 +274,9 @@ async def test_lightning_pay_invoice_pending_failure(ledger: Ledger):
|
||||
@pytest.mark.skipif(is_fake, reason="only regtest")
|
||||
async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger):
|
||||
# fill wallet
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
|
||||
# create hodl invoice
|
||||
|
||||
@@ -8,7 +8,12 @@ from cashu.core.base import MintQuoteState, Proof
|
||||
from cashu.core.errors import CashuError, KeysetNotFoundError
|
||||
from cashu.core.helpers import sum_proofs
|
||||
from cashu.core.settings import settings
|
||||
from cashu.wallet.crud import get_keysets, get_lightning_invoice, get_proofs
|
||||
from cashu.wallet.crud import (
|
||||
get_bolt11_melt_quote,
|
||||
get_bolt11_mint_quote,
|
||||
get_keysets,
|
||||
get_proofs,
|
||||
)
|
||||
from cashu.wallet.wallet import Wallet
|
||||
from cashu.wallet.wallet import Wallet as Wallet1
|
||||
from cashu.wallet.wallet import Wallet as Wallet2
|
||||
@@ -160,44 +165,41 @@ async def test_get_keysets(wallet1: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_request_mint(wallet1: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
assert invoice.payment_hash
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
assert mint_quote.request
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mint(wallet1: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
if not settings.debug_mint_only_deprecated:
|
||||
quote_resp = await wallet1.get_mint_quote(invoice.id)
|
||||
assert quote_resp.request == invoice.bolt11
|
||||
quote_resp = await wallet1.get_mint_quote(mint_quote.quote)
|
||||
assert quote_resp.request == mint_quote.request
|
||||
assert quote_resp.state == MintQuoteState.paid.value
|
||||
|
||||
expected_proof_amounts = wallet1.split_wallet_state(64)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet1.balance == 64
|
||||
|
||||
# verify that proofs in proofs_used db have the same mint_id as the invoice in the db
|
||||
assert invoice.payment_hash
|
||||
invoice_db = await get_lightning_invoice(
|
||||
db=wallet1.db, payment_hash=invoice.payment_hash, out=False
|
||||
)
|
||||
assert invoice_db
|
||||
mint_quote = await get_bolt11_mint_quote(db=wallet1.db, quote=mint_quote.quote)
|
||||
assert mint_quote
|
||||
proofs_minted = await get_proofs(
|
||||
db=wallet1.db, mint_id=invoice_db.id, table="proofs"
|
||||
db=wallet1.db, mint_id=mint_quote.quote, table="proofs"
|
||||
)
|
||||
assert len(proofs_minted) == len(expected_proof_amounts)
|
||||
assert all([p.amount in expected_proof_amounts for p in proofs_minted])
|
||||
assert all([p.mint_id == invoice.id for p in proofs_minted])
|
||||
assert all([p.mint_id == mint_quote.quote for p in proofs_minted])
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_mint_amounts(wallet1: Wallet):
|
||||
"""Mint predefined amounts"""
|
||||
amts = [1, 1, 1, 2, 2, 4, 16]
|
||||
invoice = await wallet1.request_mint(sum(amts))
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(amount=sum(amts), split=amts, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(sum(amts))
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(amount=sum(amts), split=amts, quote_id=mint_quote.quote)
|
||||
assert wallet1.balance == 27
|
||||
assert wallet1.proof_amounts == amts
|
||||
|
||||
@@ -207,9 +209,9 @@ async def test_mint_amounts_wrong_sum(wallet1: Wallet):
|
||||
"""Mint predefined amounts"""
|
||||
|
||||
amts = [1, 1, 1, 2, 2, 4, 16]
|
||||
invoice = await wallet1.request_mint(sum(amts))
|
||||
mint_quote = await wallet1.request_mint(sum(amts))
|
||||
await assert_err(
|
||||
wallet1.mint(amount=sum(amts) + 1, split=amts, id=invoice.id),
|
||||
wallet1.mint(amount=sum(amts) + 1, split=amts, quote_id=mint_quote.quote),
|
||||
"split must sum to amount",
|
||||
)
|
||||
|
||||
@@ -218,18 +220,18 @@ async def test_mint_amounts_wrong_sum(wallet1: Wallet):
|
||||
async def test_mint_amounts_wrong_order(wallet1: Wallet):
|
||||
"""Mint amount that is not part in 2^n"""
|
||||
amts = [1, 2, 3]
|
||||
invoice = await wallet1.request_mint(sum(amts))
|
||||
mint_quote = await wallet1.request_mint(sum(amts))
|
||||
await assert_err(
|
||||
wallet1.mint(amount=sum(amts), split=[1, 2, 3], id=invoice.id),
|
||||
wallet1.mint(amount=sum(amts), split=[1, 2, 3], quote_id=mint_quote.quote),
|
||||
f"Can only mint amounts with 2^n up to {2**settings.max_order}.",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_split(wallet1: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet1.balance == 64
|
||||
# the outputs we keep that we expect after the split
|
||||
expected_proof_amounts = wallet1.split_wallet_state(44)
|
||||
@@ -247,9 +249,9 @@ async def test_split(wallet1: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_swap_to_send(wallet1: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet1.balance == 64
|
||||
|
||||
# this will select 32 sats and them (nothing to keep)
|
||||
@@ -269,9 +271,9 @@ async def test_swap_to_send(wallet1: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_split_more_than_balance(wallet1: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
await assert_err(
|
||||
wallet1.split(wallet1.proofs, 128),
|
||||
# "Mint Error: inputs do not have same amount as outputs",
|
||||
@@ -283,22 +285,19 @@ async def test_split_more_than_balance(wallet1: Wallet):
|
||||
@pytest.mark.asyncio
|
||||
async def test_melt(wallet1: Wallet):
|
||||
# mint twice so we have enough to pay the second invoice back
|
||||
topup_invoice = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(topup_invoice.bolt11)
|
||||
await wallet1.mint(128, id=topup_invoice.id)
|
||||
topup_mint_quote = await wallet1.request_mint(128)
|
||||
await pay_if_regtest(topup_mint_quote.request)
|
||||
await wallet1.mint(128, quote_id=topup_mint_quote.quote)
|
||||
assert wallet1.balance == 128
|
||||
|
||||
invoice_payment_request = ""
|
||||
invoice_payment_hash = ""
|
||||
if is_regtest:
|
||||
invoice_dict = get_real_invoice(64)
|
||||
invoice_payment_hash = str(invoice_dict["r_hash"])
|
||||
invoice_payment_request = invoice_dict["payment_request"]
|
||||
|
||||
if is_fake:
|
||||
invoice = await wallet1.request_mint(64)
|
||||
invoice_payment_hash = str(invoice.payment_hash)
|
||||
invoice_payment_request = invoice.bolt11
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
invoice_payment_request = mint_quote.request
|
||||
|
||||
quote = await wallet1.melt_quote(invoice_payment_request)
|
||||
total_amount = quote.amount + quote.fee_reserve
|
||||
@@ -334,17 +333,16 @@ async def test_melt(wallet1: Wallet):
|
||||
assert melt_response.change[0].id == send_proofs[0].id, "Wrong keyset returned"
|
||||
|
||||
# verify that proofs in proofs_used db have the same melt_id as the invoice in the db
|
||||
assert invoice_payment_hash, "No payment hash in invoice"
|
||||
invoice_db = await get_lightning_invoice(
|
||||
db=wallet1.db, payment_hash=invoice_payment_hash, out=True
|
||||
melt_quote_db = await get_bolt11_melt_quote(
|
||||
db=wallet1.db, request=invoice_payment_request
|
||||
)
|
||||
assert invoice_db, "No invoice in db"
|
||||
assert melt_quote_db, "No invoice in db"
|
||||
proofs_used = await get_proofs(
|
||||
db=wallet1.db, melt_id=invoice_db.id, table="proofs_used"
|
||||
db=wallet1.db, melt_id=melt_quote_db.quote, table="proofs_used"
|
||||
)
|
||||
|
||||
assert len(proofs_used) == len(send_proofs), "Not all proofs used"
|
||||
assert all([p.melt_id == invoice_db.id for p in proofs_used]), "Wrong melt_id"
|
||||
assert all([p.melt_id == melt_quote_db.quote for p in proofs_used]), "Wrong melt_id"
|
||||
|
||||
# the payment was without fees so we need to remove it from the total amount
|
||||
assert wallet1.balance == 128 - (total_amount - quote.fee_reserve), "Wrong balance"
|
||||
@@ -353,9 +351,9 @@ async def test_melt(wallet1: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_swap_to_send_more_than_balance(wallet1: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
await assert_err(
|
||||
wallet1.swap_to_send(wallet1.proofs, 128, set_reserved=True),
|
||||
"balance too low.",
|
||||
@@ -366,9 +364,9 @@ async def test_swap_to_send_more_than_balance(wallet1: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_double_spend(wallet1: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
doublespend = await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
doublespend = await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
await wallet1.split(wallet1.proofs, 20)
|
||||
await assert_err(
|
||||
wallet1.split(doublespend, 20),
|
||||
@@ -380,9 +378,9 @@ async def test_double_spend(wallet1: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_duplicate_proofs_double_spent(wallet1: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
doublespend = await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
doublespend = await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
await assert_err(
|
||||
wallet1.split(wallet1.proofs + doublespend, 20),
|
||||
"Mint Error: duplicate proofs.",
|
||||
@@ -394,9 +392,9 @@ async def test_duplicate_proofs_double_spent(wallet1: Wallet):
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.skipif(is_github_actions, reason="GITHUB_ACTIONS")
|
||||
async def test_split_race_condition(wallet1: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
# run two splits in parallel
|
||||
import asyncio
|
||||
|
||||
@@ -411,9 +409,9 @@ async def test_split_race_condition(wallet1: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
_, spendable_proofs = await wallet1.swap_to_send(
|
||||
wallet1.proofs, 32, set_reserved=True
|
||||
)
|
||||
@@ -430,9 +428,9 @@ async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet):
|
||||
@pytest.mark.asyncio
|
||||
async def test_invalidate_all_proofs(wallet1: Wallet):
|
||||
"""Try to invalidate proofs that have not been spent yet. Should not work!"""
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
await wallet1.invalidate(wallet1.proofs)
|
||||
assert wallet1.balance == 0
|
||||
|
||||
@@ -440,18 +438,18 @@ async def test_invalidate_all_proofs(wallet1: Wallet):
|
||||
@pytest.mark.asyncio
|
||||
async def test_invalidate_unspent_proofs_with_checking(wallet1: Wallet):
|
||||
"""Try to invalidate proofs that have not been spent yet but force no check."""
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
await wallet1.invalidate(wallet1.proofs, check_spendable=True)
|
||||
assert wallet1.balance == 64
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_split_invalid_amount(wallet1: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
await assert_err(
|
||||
wallet1.split(wallet1.proofs, -1),
|
||||
"amount can't be negative",
|
||||
@@ -460,9 +458,9 @@ async def test_split_invalid_amount(wallet1: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_token_state(wallet1: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet1.balance == 64
|
||||
resp = await wallet1.check_proof_state(wallet1.proofs)
|
||||
assert resp.states[0].state.value == "UNSPENT"
|
||||
|
||||
@@ -33,12 +33,14 @@ async def test_invoice(wallet: Wallet):
|
||||
while state.pending:
|
||||
print("checking invoice state")
|
||||
response2 = client.get(
|
||||
f"/lightning/invoice_state?payment_hash={invoice_response.checking_id}"
|
||||
f"/lightning/invoice_state?payment_request={invoice_response.payment_request}"
|
||||
)
|
||||
state = PaymentStatus.parse_obj(response2.json())
|
||||
await asyncio.sleep(0.1)
|
||||
print("state:", state)
|
||||
print("paid")
|
||||
await wallet.load_proofs()
|
||||
assert wallet.available_balance >= 100
|
||||
|
||||
|
||||
@pytest.mark.skipif(is_regtest, reason="regtest")
|
||||
@@ -175,7 +177,7 @@ async def test_flow(wallet: Wallet):
|
||||
while state.pending:
|
||||
print("checking invoice state")
|
||||
response2 = client.get(
|
||||
f"/lightning/invoice_state?payment_hash={invoice_response.checking_id}"
|
||||
f"/lightning/invoice_state?payment_request={invoice_response.payment_request}"
|
||||
)
|
||||
state = PaymentStatus.parse_obj(response2.json())
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
@@ -32,6 +32,10 @@ def get_invoice_from_invoices_command(output: str) -> dict[str, str]:
|
||||
removed_empty_and_hiphens = [
|
||||
value for value in splitted if value and not value.startswith("-----")
|
||||
]
|
||||
# filter only lines that have ": " in them
|
||||
removed_empty_and_hiphens = [
|
||||
value for value in removed_empty_and_hiphens if ": " in value
|
||||
]
|
||||
dict_output = {
|
||||
f"{value.split(': ')[0]}": value.split(": ")[1]
|
||||
for value in removed_empty_and_hiphens
|
||||
@@ -41,7 +45,8 @@ def get_invoice_from_invoices_command(output: str) -> dict[str, str]:
|
||||
|
||||
|
||||
async def reset_invoices(wallet: Wallet):
|
||||
await wallet.db.execute("DELETE FROM invoices")
|
||||
await wallet.db.execute("DELETE FROM bolt11_melt_quotes")
|
||||
await wallet.db.execute("DELETE FROM bolt11_mint_quotes")
|
||||
|
||||
|
||||
async def init_wallet():
|
||||
@@ -204,8 +209,8 @@ def test_invoices_with_minting(cli_prefix):
|
||||
# arrange
|
||||
wallet1 = asyncio.run(init_wallet())
|
||||
asyncio.run(reset_invoices(wallet=wallet1))
|
||||
invoice = asyncio.run(wallet1.request_mint(64))
|
||||
asyncio.run(pay_if_regtest(invoice.bolt11))
|
||||
mint_quote = asyncio.run(wallet1.request_mint(64))
|
||||
asyncio.run(pay_if_regtest(mint_quote.request))
|
||||
# act
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
@@ -217,18 +222,14 @@ def test_invoices_with_minting(cli_prefix):
|
||||
print("INVOICES --mint")
|
||||
assert result.exception is None
|
||||
assert result.exit_code == 0
|
||||
assert "No invoices found." not in result.output
|
||||
assert "ID" in result.output
|
||||
assert "Paid" in result.output
|
||||
assert get_invoice_from_invoices_command(result.output)["ID"] == invoice.id
|
||||
assert get_invoice_from_invoices_command(result.output)["Paid"] == "True"
|
||||
assert "Received 64 sat" in result.output
|
||||
|
||||
|
||||
def test_invoices_without_minting(cli_prefix):
|
||||
# arrange
|
||||
wallet1 = asyncio.run(init_wallet())
|
||||
asyncio.run(reset_invoices(wallet=wallet1))
|
||||
invoice = asyncio.run(wallet1.request_mint(64))
|
||||
mint_quote = asyncio.run(wallet1.request_mint(64))
|
||||
|
||||
# act
|
||||
runner = CliRunner()
|
||||
@@ -243,9 +244,11 @@ def test_invoices_without_minting(cli_prefix):
|
||||
assert result.exit_code == 0
|
||||
assert "No invoices found." not in result.output
|
||||
assert "ID" in result.output
|
||||
assert "Paid" in result.output
|
||||
assert get_invoice_from_invoices_command(result.output)["ID"] == invoice.id
|
||||
assert get_invoice_from_invoices_command(result.output)["Paid"] == str(invoice.paid)
|
||||
assert "State" in result.output
|
||||
assert get_invoice_from_invoices_command(result.output)["ID"] == mint_quote.quote
|
||||
assert get_invoice_from_invoices_command(result.output)["State"] == str(
|
||||
mint_quote.state
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skipif(not is_fake, reason="only on fakewallet")
|
||||
@@ -259,11 +262,11 @@ def test_invoices_with_onlypaid_option(cli_prefix):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
[*cli_prefix, "invoices", "--only-paid", "--mint"],
|
||||
[*cli_prefix, "invoices", "--only-paid"],
|
||||
)
|
||||
|
||||
# assert
|
||||
print("INVOICES --only-paid --mint")
|
||||
print("INVOICES --only-paid")
|
||||
assert result.exception is None
|
||||
assert result.exit_code == 0
|
||||
assert "No invoices found." in result.output
|
||||
@@ -314,7 +317,7 @@ def test_invoices_with_onlyunpaid_option_without_minting(cli_prefix):
|
||||
# arrange
|
||||
wallet1 = asyncio.run(init_wallet())
|
||||
asyncio.run(reset_invoices(wallet=wallet1))
|
||||
invoice = asyncio.run(wallet1.request_mint(64))
|
||||
mint_quote = asyncio.run(wallet1.request_mint(64))
|
||||
|
||||
# act
|
||||
runner = CliRunner()
|
||||
@@ -329,9 +332,11 @@ def test_invoices_with_onlyunpaid_option_without_minting(cli_prefix):
|
||||
assert result.exit_code == 0
|
||||
assert "No invoices found." not in result.output
|
||||
assert "ID" in result.output
|
||||
assert "Paid" in result.output
|
||||
assert get_invoice_from_invoices_command(result.output)["ID"] == invoice.id
|
||||
assert get_invoice_from_invoices_command(result.output)["Paid"] == str(invoice.paid)
|
||||
assert "State" in result.output
|
||||
assert get_invoice_from_invoices_command(result.output)["ID"] == mint_quote.quote
|
||||
assert get_invoice_from_invoices_command(result.output)["State"] == str(
|
||||
mint_quote.state
|
||||
)
|
||||
|
||||
|
||||
def test_invoices_with_both_onlypaid_and_onlyunpaid_options(cli_prefix):
|
||||
@@ -374,7 +379,7 @@ def test_invoices_with_pending_option_without_minting(cli_prefix):
|
||||
# arrange
|
||||
wallet1 = asyncio.run(init_wallet())
|
||||
asyncio.run(reset_invoices(wallet=wallet1))
|
||||
invoice = asyncio.run(wallet1.request_mint(64))
|
||||
mint_quote = asyncio.run(wallet1.request_mint(64))
|
||||
|
||||
# act
|
||||
runner = CliRunner()
|
||||
@@ -389,9 +394,11 @@ def test_invoices_with_pending_option_without_minting(cli_prefix):
|
||||
assert result.exit_code == 0
|
||||
assert "No invoices found." not in result.output
|
||||
assert "ID" in result.output
|
||||
assert "Paid" in result.output
|
||||
assert get_invoice_from_invoices_command(result.output)["ID"] == invoice.id
|
||||
assert get_invoice_from_invoices_command(result.output)["Paid"] == str(invoice.paid)
|
||||
assert "State" in result.output
|
||||
assert get_invoice_from_invoices_command(result.output)["ID"] == mint_quote.quote
|
||||
assert get_invoice_from_invoices_command(result.output)["State"] == str(
|
||||
mint_quote.state
|
||||
)
|
||||
|
||||
|
||||
def test_wallets(cli_prefix):
|
||||
|
||||
@@ -57,9 +57,9 @@ async def wallet2():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_htlc_secret(wallet1: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
preimage = "00000000000000000000000000000000"
|
||||
preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
|
||||
secret = await wallet1.create_htlc_lock(preimage=preimage)
|
||||
@@ -68,9 +68,9 @@ async def test_create_htlc_secret(wallet1: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_htlc_split(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
preimage = "00000000000000000000000000000000"
|
||||
preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
|
||||
secret = await wallet1.create_htlc_lock(preimage=preimage)
|
||||
@@ -81,9 +81,9 @@ async def test_htlc_split(wallet1: Wallet, wallet2: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_htlc_redeem_with_preimage(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
preimage = "00000000000000000000000000000000"
|
||||
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
|
||||
secret = await wallet1.create_htlc_lock(preimage=preimage)
|
||||
@@ -95,9 +95,9 @@ async def test_htlc_redeem_with_preimage(wallet1: Wallet, wallet2: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_htlc_redeem_with_wrong_preimage(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
preimage = "00000000000000000000000000000000"
|
||||
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
|
||||
secret = await wallet1.create_htlc_lock(
|
||||
@@ -113,9 +113,9 @@ async def test_htlc_redeem_with_wrong_preimage(wallet1: Wallet, wallet2: Wallet)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_htlc_redeem_with_no_signature(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
preimage = "00000000000000000000000000000000"
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
|
||||
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
|
||||
@@ -133,9 +133,9 @@ async def test_htlc_redeem_with_no_signature(wallet1: Wallet, wallet2: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_htlc_redeem_with_wrong_signature(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
preimage = "00000000000000000000000000000000"
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
|
||||
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
|
||||
@@ -157,9 +157,9 @@ async def test_htlc_redeem_with_wrong_signature(wallet1: Wallet, wallet2: Wallet
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_htlc_redeem_with_correct_signature(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
preimage = "00000000000000000000000000000000"
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
|
||||
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
|
||||
@@ -177,9 +177,9 @@ async def test_htlc_redeem_with_correct_signature(wallet1: Wallet, wallet2: Wall
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_htlc_redeem_with_2_of_1_signatures(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
preimage = "00000000000000000000000000000000"
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
@@ -201,9 +201,9 @@ async def test_htlc_redeem_with_2_of_1_signatures(wallet1: Wallet, wallet2: Wall
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_htlc_redeem_with_2_of_2_signatures(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
preimage = "00000000000000000000000000000000"
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
@@ -227,9 +227,9 @@ async def test_htlc_redeem_with_2_of_2_signatures(wallet1: Wallet, wallet2: Wall
|
||||
async def test_htlc_redeem_with_2_of_2_signatures_with_duplicate_pubkeys(
|
||||
wallet1: Wallet, wallet2: Wallet
|
||||
):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
preimage = "00000000000000000000000000000000"
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
|
||||
pubkey_wallet2 = pubkey_wallet1
|
||||
@@ -256,9 +256,9 @@ async def test_htlc_redeem_with_2_of_2_signatures_with_duplicate_pubkeys(
|
||||
async def test_htlc_redeem_with_3_of_3_signatures_but_only_2_provided(
|
||||
wallet1: Wallet, wallet2: Wallet
|
||||
):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
preimage = "00000000000000000000000000000000"
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
@@ -285,9 +285,9 @@ async def test_htlc_redeem_with_3_of_3_signatures_but_only_2_provided(
|
||||
async def test_htlc_redeem_with_2_of_3_signatures_with_2_valid_and_1_invalid_provided(
|
||||
wallet1: Wallet, wallet2: Wallet
|
||||
):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
preimage = "00000000000000000000000000000000"
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
@@ -316,9 +316,9 @@ async def test_htlc_redeem_with_2_of_3_signatures_with_2_valid_and_1_invalid_pro
|
||||
async def test_htlc_redeem_with_3_of_3_signatures_with_2_valid_and_1_invalid_provided(
|
||||
wallet1: Wallet, wallet2: Wallet
|
||||
):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
preimage = "00000000000000000000000000000000"
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
@@ -349,9 +349,9 @@ async def test_htlc_redeem_with_3_of_3_signatures_with_2_valid_and_1_invalid_pro
|
||||
async def test_htlc_redeem_hashlock_wrong_signature_timelock_correct_signature(
|
||||
wallet1: Wallet, wallet2: Wallet
|
||||
):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
preimage = "00000000000000000000000000000000"
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
@@ -383,9 +383,9 @@ async def test_htlc_redeem_hashlock_wrong_signature_timelock_correct_signature(
|
||||
async def test_htlc_redeem_hashlock_wrong_signature_timelock_wrong_signature(
|
||||
wallet1: Wallet, wallet2: Wallet
|
||||
):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
preimage = "00000000000000000000000000000000"
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
|
||||
@@ -81,8 +81,7 @@ async def test_check_invoice_internal(wallet: LightningWallet):
|
||||
# fill wallet
|
||||
invoice = await wallet.create_invoice(64)
|
||||
assert invoice.payment_request
|
||||
assert invoice.checking_id
|
||||
status = await wallet.get_invoice_status(invoice.checking_id)
|
||||
status = await wallet.get_invoice_status(invoice.payment_request)
|
||||
assert status.settled
|
||||
|
||||
|
||||
@@ -92,11 +91,10 @@ async def test_check_invoice_external(wallet: LightningWallet):
|
||||
# fill wallet
|
||||
invoice = await wallet.create_invoice(64)
|
||||
assert invoice.payment_request
|
||||
assert invoice.checking_id
|
||||
status = await wallet.get_invoice_status(invoice.checking_id)
|
||||
status = await wallet.get_invoice_status(invoice.payment_request)
|
||||
assert not status.settled
|
||||
await pay_if_regtest(invoice.payment_request)
|
||||
status = await wallet.get_invoice_status(invoice.checking_id)
|
||||
status = await wallet.get_invoice_status(invoice.payment_request)
|
||||
assert status.settled
|
||||
|
||||
|
||||
@@ -106,8 +104,7 @@ async def test_pay_invoice_internal(wallet: LightningWallet):
|
||||
# fill wallet
|
||||
invoice = await wallet.create_invoice(64)
|
||||
assert invoice.payment_request
|
||||
assert invoice.checking_id
|
||||
await wallet.get_invoice_status(invoice.checking_id)
|
||||
await wallet.get_invoice_status(invoice.payment_request)
|
||||
assert wallet.available_balance >= 64
|
||||
|
||||
# pay invoice
|
||||
@@ -118,8 +115,7 @@ async def test_pay_invoice_internal(wallet: LightningWallet):
|
||||
assert status.settled
|
||||
|
||||
# check payment
|
||||
assert invoice2.checking_id
|
||||
status = await wallet.get_payment_status(invoice2.checking_id)
|
||||
status = await wallet.get_payment_status(invoice2.payment_request)
|
||||
assert status.settled
|
||||
|
||||
|
||||
@@ -129,9 +125,8 @@ async def test_pay_invoice_external(wallet: LightningWallet):
|
||||
# fill wallet
|
||||
invoice = await wallet.create_invoice(64)
|
||||
assert invoice.payment_request
|
||||
assert invoice.checking_id
|
||||
await pay_if_regtest(invoice.payment_request)
|
||||
status = await wallet.get_invoice_status(invoice.checking_id)
|
||||
status = await wallet.get_invoice_status(invoice.payment_request)
|
||||
assert status.settled
|
||||
assert wallet.available_balance >= 64
|
||||
|
||||
@@ -141,7 +136,5 @@ async def test_pay_invoice_external(wallet: LightningWallet):
|
||||
|
||||
assert status.settled
|
||||
|
||||
# check payment
|
||||
assert status.checking_id
|
||||
status = await wallet.get_payment_status(status.checking_id)
|
||||
# check payment)
|
||||
assert status.settled
|
||||
|
||||
@@ -59,18 +59,18 @@ async def wallet2():
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_p2pk_pubkey(wallet1: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
pubkey = await wallet1.create_p2pk_pubkey()
|
||||
PublicKey(bytes.fromhex(pubkey), raw=True)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_p2pk(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
# p2pk test
|
||||
secret_lock = await wallet1.create_p2pk_lock(pubkey_wallet2) # sender side
|
||||
@@ -92,9 +92,9 @@ async def test_p2pk(wallet1: Wallet, wallet2: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_p2pk_sig_all(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
# p2pk test
|
||||
secret_lock = await wallet1.create_p2pk_lock(
|
||||
@@ -108,9 +108,9 @@ async def test_p2pk_sig_all(wallet1: Wallet, wallet2: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_p2pk_receive_with_wrong_private_key(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side
|
||||
# sender side
|
||||
secret_lock = await wallet1.create_p2pk_lock(pubkey_wallet2) # sender side
|
||||
@@ -129,9 +129,9 @@ async def test_p2pk_receive_with_wrong_private_key(wallet1: Wallet, wallet2: Wal
|
||||
async def test_p2pk_short_locktime_receive_with_wrong_private_key(
|
||||
wallet1: Wallet, wallet2: Wallet
|
||||
):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side
|
||||
# sender side
|
||||
secret_lock = await wallet1.create_p2pk_lock(
|
||||
@@ -155,9 +155,9 @@ async def test_p2pk_short_locktime_receive_with_wrong_private_key(
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_p2pk_locktime_with_refund_pubkey(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side
|
||||
# sender side
|
||||
garbage_pubkey = PrivateKey().pubkey
|
||||
@@ -184,9 +184,9 @@ async def test_p2pk_locktime_with_refund_pubkey(wallet1: Wallet, wallet2: Wallet
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_p2pk_locktime_with_wrong_refund_pubkey(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
await wallet2.create_p2pk_pubkey() # receiver side
|
||||
# sender side
|
||||
garbage_pubkey = PrivateKey().pubkey
|
||||
@@ -220,9 +220,9 @@ async def test_p2pk_locktime_with_wrong_refund_pubkey(wallet1: Wallet, wallet2:
|
||||
async def test_p2pk_locktime_with_second_refund_pubkey(
|
||||
wallet1: Wallet, wallet2: Wallet
|
||||
):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey() # receiver side
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side
|
||||
# sender side
|
||||
@@ -252,9 +252,9 @@ async def test_p2pk_locktime_with_second_refund_pubkey(
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_p2pk_multisig_2_of_2(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
assert pubkey_wallet1 != pubkey_wallet2
|
||||
@@ -274,9 +274,9 @@ async def test_p2pk_multisig_2_of_2(wallet1: Wallet, wallet2: Wallet):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_p2pk_multisig_duplicate_signature(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
assert pubkey_wallet1 != pubkey_wallet2
|
||||
@@ -298,9 +298,9 @@ async def test_p2pk_multisig_duplicate_signature(wallet1: Wallet, wallet2: Walle
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_p2pk_multisig_quorum_not_met_1_of_2(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
assert pubkey_wallet1 != pubkey_wallet2
|
||||
@@ -319,9 +319,9 @@ async def test_p2pk_multisig_quorum_not_met_1_of_2(wallet1: Wallet, wallet2: Wal
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_p2pk_multisig_quorum_not_met_2_of_3(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
assert pubkey_wallet1 != pubkey_wallet2
|
||||
@@ -344,9 +344,9 @@ async def test_p2pk_multisig_quorum_not_met_2_of_3(wallet1: Wallet, wallet2: Wal
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_p2pk_multisig_with_duplicate_publickey(wallet1: Wallet, wallet2: Wallet):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
# p2pk test
|
||||
secret_lock = await wallet1.create_p2pk_lock(
|
||||
@@ -362,9 +362,9 @@ async def test_p2pk_multisig_with_duplicate_publickey(wallet1: Wallet, wallet2:
|
||||
async def test_p2pk_multisig_with_wrong_first_private_key(
|
||||
wallet1: Wallet, wallet2: Wallet
|
||||
):
|
||||
invoice = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet1.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet1.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet1.mint(64, quote_id=mint_quote.quote)
|
||||
await wallet1.create_p2pk_pubkey()
|
||||
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||
wrong_pubklic_key = PrivateKey().pubkey
|
||||
|
||||
@@ -32,9 +32,9 @@ async def wallet():
|
||||
@pytest.mark.skipif(is_fake, reason="only regtest")
|
||||
async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger):
|
||||
# fill wallet
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
|
||||
# create hodl invoice
|
||||
@@ -70,9 +70,9 @@ async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger):
|
||||
@pytest.mark.skipif(is_fake, reason="only regtest")
|
||||
async def test_regtest_failed_quote(wallet: Wallet, ledger: Ledger):
|
||||
# fill wallet
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet.balance == 64
|
||||
|
||||
# create hodl invoice
|
||||
|
||||
@@ -40,9 +40,9 @@ async def test_regtest_pay_mpp(wallet: Wallet, ledger: Ledger):
|
||||
assert wallet.mint_info.supports_mpp("bolt11", wallet.unit)
|
||||
|
||||
# top up wallet twice so we have enough for two payments
|
||||
topup_invoice = await wallet.request_mint(128)
|
||||
await pay_if_regtest(topup_invoice.bolt11)
|
||||
proofs1 = await wallet.mint(128, id=topup_invoice.id)
|
||||
topup_mint_quote = await wallet.request_mint(128)
|
||||
await pay_if_regtest(topup_mint_quote.request)
|
||||
proofs1 = await wallet.mint(128, quote_id=topup_mint_quote.quote)
|
||||
assert wallet.balance == 128
|
||||
|
||||
# this is the invoice we want to pay in two parts
|
||||
@@ -95,19 +95,19 @@ async def test_regtest_pay_mpp_incomplete_payment(wallet: Wallet, ledger: Ledger
|
||||
assert wallet.mint_info.supports_mpp("bolt11", wallet.unit)
|
||||
|
||||
# top up wallet twice so we have enough for three payments
|
||||
topup_invoice = await wallet.request_mint(128)
|
||||
await pay_if_regtest(topup_invoice.bolt11)
|
||||
proofs1 = await wallet.mint(128, id=topup_invoice.id)
|
||||
topup_mint_quote = await wallet.request_mint(128)
|
||||
await pay_if_regtest(topup_mint_quote.request)
|
||||
proofs1 = await wallet.mint(128, quote_id=topup_mint_quote.quote)
|
||||
assert wallet.balance == 128
|
||||
|
||||
topup_invoice = await wallet.request_mint(128)
|
||||
await pay_if_regtest(topup_invoice.bolt11)
|
||||
proofs2 = await wallet.mint(128, id=topup_invoice.id)
|
||||
topup_mint_quote = await wallet.request_mint(128)
|
||||
await pay_if_regtest(topup_mint_quote.request)
|
||||
proofs2 = await wallet.mint(128, quote_id=topup_mint_quote.quote)
|
||||
assert wallet.balance == 256
|
||||
|
||||
topup_invoice = await wallet.request_mint(128)
|
||||
await pay_if_regtest(topup_invoice.bolt11)
|
||||
proofs3 = await wallet.mint(128, id=topup_invoice.id)
|
||||
topup_mint_quote = await wallet.request_mint(128)
|
||||
await pay_if_regtest(topup_mint_quote.request)
|
||||
proofs3 = await wallet.mint(128, quote_id=topup_mint_quote.quote)
|
||||
assert wallet.balance == 384
|
||||
|
||||
# this is the invoice we want to pay in two parts
|
||||
|
||||
@@ -156,9 +156,9 @@ async def test_generate_secrets_from_to(wallet3: Wallet):
|
||||
@pytest.mark.asyncio
|
||||
async def test_restore_wallet_after_mint(wallet3: Wallet):
|
||||
await reset_wallet_db(wallet3)
|
||||
invoice = await wallet3.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet3.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet3.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet3.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet3.balance == 64
|
||||
await reset_wallet_db(wallet3)
|
||||
await wallet3.load_proofs()
|
||||
@@ -192,9 +192,9 @@ async def test_restore_wallet_after_swap_to_send(wallet3: Wallet):
|
||||
)
|
||||
await reset_wallet_db(wallet3)
|
||||
|
||||
invoice = await wallet3.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet3.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet3.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet3.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet3.balance == 64
|
||||
|
||||
_, spendable_proofs = await wallet3.swap_to_send(
|
||||
@@ -217,9 +217,9 @@ async def test_restore_wallet_after_send_and_receive(wallet3: Wallet, wallet2: W
|
||||
"hello rug want adapt talent together lunar method bean expose beef position"
|
||||
)
|
||||
await reset_wallet_db(wallet3)
|
||||
invoice = await wallet3.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet3.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet3.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet3.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet3.balance == 64
|
||||
|
||||
_, spendable_proofs = await wallet3.swap_to_send(
|
||||
@@ -260,9 +260,9 @@ async def test_restore_wallet_after_send_and_self_receive(wallet3: Wallet):
|
||||
)
|
||||
await reset_wallet_db(wallet3)
|
||||
|
||||
invoice = await wallet3.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet3.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet3.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet3.mint(64, quote_id=mint_quote.quote)
|
||||
assert wallet3.balance == 64
|
||||
|
||||
_, spendable_proofs = await wallet3.swap_to_send(
|
||||
@@ -289,9 +289,9 @@ async def test_restore_wallet_after_send_twice(
|
||||
wallet3.private_key = PrivateKey()
|
||||
await reset_wallet_db(wallet3)
|
||||
|
||||
invoice = await wallet3.request_mint(2)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet3.mint(2, id=invoice.id)
|
||||
mint_quote = await wallet3.request_mint(2)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet3.mint(2, quote_id=mint_quote.quote)
|
||||
box.add(wallet3.proofs)
|
||||
assert wallet3.balance == 2
|
||||
|
||||
@@ -348,9 +348,9 @@ async def test_restore_wallet_after_send_and_self_receive_nonquadratic_value(
|
||||
)
|
||||
await reset_wallet_db(wallet3)
|
||||
|
||||
invoice = await wallet3.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet3.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet3.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet3.mint(64, quote_id=mint_quote.quote)
|
||||
box.add(wallet3.proofs)
|
||||
assert wallet3.balance == 64
|
||||
|
||||
|
||||
@@ -44,10 +44,10 @@ async def test_wallet_subscription_mint(wallet: Wallet):
|
||||
nonlocal triggered, msg_stack
|
||||
triggered = True
|
||||
msg_stack.append(msg)
|
||||
asyncio.run(wallet.mint(int(invoice.amount), id=invoice.id))
|
||||
asyncio.run(wallet.mint(int(mint_quote.amount), quote_id=mint_quote.quote))
|
||||
|
||||
invoice, sub = await wallet.request_mint_with_callback(128, callback=callback)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
mint_quote, sub = await wallet.request_mint_with_callback(128, callback=callback)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
wait = settings.fakewallet_delay_incoming_payment or 2
|
||||
await asyncio.sleep(wait + 2)
|
||||
|
||||
@@ -66,9 +66,9 @@ async def test_wallet_subscription_swap(wallet: Wallet):
|
||||
if not wallet.mint_info.supports_nut(WEBSOCKETS_NUT):
|
||||
pytest.skip("No websocket support")
|
||||
|
||||
invoice = await wallet.request_mint(64)
|
||||
await pay_if_regtest(invoice.bolt11)
|
||||
await wallet.mint(64, id=invoice.id)
|
||||
mint_quote = await wallet.request_mint(64)
|
||||
await pay_if_regtest(mint_quote.request)
|
||||
await wallet.mint(64, quote_id=mint_quote.quote)
|
||||
|
||||
triggered = False
|
||||
msg_stack: list[JSONRPCNotficationParams] = []
|
||||
|
||||
Reference in New Issue
Block a user