Mint: table locks (#566)

* clean up db

* db: table lock

* db.table_with_schema

* fix encrypt.py

* postgres nowait

* add timeout to lock

* melt quote state in db

* kinda working

* kinda working with postgres

* remove dispose

* getting there

* porperly clean up db for tests

* faster tests

* configure connection pooling

* try github with connection pool

* invoice dispatcher does not lock db

* fakewallet: pay_if_regtest waits

* pay fakewallet invoices

* add more

* faster

* slower

* pay_if_regtest async

* do not lock the invoice dispatcher

* test: do I get disk I/O errors if we disable the invoice_callback_dispatcher?

* fix fake so it workss without a callback dispatchert

* test on github

* readd tasks

* refactor

* increase time for lock invoice disatcher

* try avoiding a race

* remove task

* github actions: test regtest with postgres

* mint per module

* no connection pool for testing

* enable pool

* do not resend paid event

* reuse connection

* close db connections

* sessions

* enable debug

* dispose engine

* disable connection pool for tests

* enable connection pool for postgres only

* clean up shutdown routine

* remove wait for lightning fakewallet lightning invoice

* cancel invoice listener tasks on shutdown

* fakewallet conftest: decrease outgoing delay

* delay payment and set postgres only if needed

* disable fail fast for regtest

* clean up regtest.yml

* change order of tests_db.py

* row-specific mint_quote locking

* refactor

* fix lock statement

* refactor swap

* refactor

* remove psycopg2

* add connection string example to .env.example

* remove unnecessary pay

* shorter sleep in test_wallet_subscription_swap
This commit is contained in:
callebtc
2024-07-08 18:05:57 +02:00
committed by GitHub
parent af636db545
commit 6a0a370ba5
46 changed files with 1933 additions and 1157 deletions

View File

@@ -22,7 +22,8 @@ from cashu.mint.ledger import Ledger
SERVER_PORT = 3337
SERVER_ENDPOINT = f"http://localhost:{SERVER_PORT}"
settings.debug = False
settings.debug = True
settings.log_level = "TRACE"
settings.cashu_dir = "./test_data/"
settings.mint_host = "localhost"
settings.mint_port = SERVER_PORT
@@ -49,6 +50,7 @@ settings.mint_transaction_rate_limit_per_minute = 60
settings.mint_lnd_enable_mpp = True
settings.mint_clnrest_enable_mpp = False
settings.mint_input_fee_ppk = 0
settings.db_connection_pool = True
assert "test" in settings.cashu_dir
shutil.rmtree(settings.cashu_dir, ignore_errors=True)
@@ -83,11 +85,6 @@ class UvicornServer(multiprocessing.Process):
async def ledger():
async def start_mint_init(ledger: Ledger) -> Ledger:
await migrate_databases(ledger.db, migrations_mint)
# add a new keyset (with a new ID) which will be duplicated with a keyset with an
# old ID by mint migration m018_duplicate_deprecated_keyset_ids
# await ledger.activate_keyset(derivation_path=settings.mint_derivation_path, version="0.15.0")
# await migrations_mint.m018_duplicate_deprecated_keyset_ids(ledger.db)
ledger = Ledger(
db=Database("mint", settings.mint_database),
seed=settings.mint_private_key,
@@ -107,8 +104,10 @@ async def ledger():
# clear postgres database
db = Database("mint", settings.mint_database)
async with db.connect() as conn:
# drop all tables
await conn.execute("DROP SCHEMA public CASCADE;")
await conn.execute("CREATE SCHEMA public;")
await db.engine.dispose()
wallets_module = importlib.import_module("cashu.lightning")
lightning_backend = getattr(wallets_module, settings.mint_backend_bolt11_sat)()
@@ -125,6 +124,7 @@ async def ledger():
ledger = await start_mint_init(ledger)
yield ledger
print("teardown")
await ledger.shutdown_ledger()
# # This fixture is used for tests that require API access to the mint
@@ -134,6 +134,7 @@ def mint():
"cashu.mint.app:app",
port=settings.mint_listen_port,
host=settings.mint_listen_host,
log_level="trace",
)
server = UvicornServer(config=config)

View File

@@ -1,3 +1,4 @@
import asyncio
import hashlib
import importlib
import json
@@ -6,13 +7,44 @@ import random
import string
import time
from subprocess import PIPE, Popen, TimeoutExpired
from typing import Tuple
from typing import List, Tuple, Union
from loguru import logger
from cashu.core.errors import CashuError
from cashu.core.settings import settings
async def assert_err(f, msg: Union[str, CashuError]):
"""Compute f() and expect an error message 'msg'."""
try:
await f
except Exception as exc:
error_message: str = str(exc.args[0])
if isinstance(msg, CashuError):
if msg.detail not in error_message:
raise Exception(
f"CashuError. Expected error: {msg.detail}, got: {error_message}"
)
return
if msg not in error_message:
raise Exception(f"Expected error: {msg}, got: {error_message}")
return
raise Exception(f"Expected error: {msg}, got no error")
async def assert_err_multiple(f, msgs: List[str]):
"""Compute f() and expect an error message 'msg'."""
try:
await f
except Exception as exc:
for msg in msgs:
if msg in str(exc.args[0]):
return
raise Exception(f"Expected error: {msgs}, got: {exc.args[0]}")
raise Exception(f"Expected error: {msgs}, got no error")
def get_random_string(N: int = 10):
return "".join(
random.SystemRandom().choice(string.ascii_uppercase + string.digits)
@@ -157,6 +189,9 @@ def pay_onchain(address: str, sats: int) -> str:
return run_cmd(cmd)
def pay_if_regtest(bolt11: str):
async def pay_if_regtest(bolt11: str):
if is_regtest:
pay_real_invoice(bolt11)
if is_fake:
await asyncio.sleep(settings.fakewallet_delay_incoming_payment or 0)
await asyncio.sleep(0.1)

View File

@@ -1,15 +1,81 @@
import asyncio
import datetime
import os
import time
from typing import List
import pytest
import pytest_asyncio
from cashu.core import db
from cashu.core.db import Connection, timestamp_now
from cashu.core.db import Connection
from cashu.core.migrations import backup_database
from cashu.core.settings import settings
from cashu.mint.ledger import Ledger
from tests.helpers import is_github_actions, is_postgres
from cashu.wallet.wallet import Wallet
from tests.conftest import SERVER_ENDPOINT
from tests.helpers import is_github_actions, is_postgres, pay_if_regtest
async def assert_err(f, msg):
"""Compute f() and expect an error message 'msg'."""
try:
await f
except Exception as exc:
if msg not in str(exc.args[0]):
raise Exception(f"Expected error: {msg}, got: {exc.args[0]}")
return
raise Exception(f"Expected error: {msg}, got no error")
async def assert_err_multiple(f, msgs: List[str]):
"""Compute f() and expect an error message 'msg'."""
try:
await f
except Exception as exc:
for msg in msgs:
if msg in str(exc.args[0]):
return
raise Exception(f"Expected error: {msgs}, got: {exc.args[0]}")
raise Exception(f"Expected error: {msgs}, got no error")
@pytest_asyncio.fixture(scope="function")
async def wallet():
wallet = await Wallet.with_db(
url=SERVER_ENDPOINT,
db="test_data/wallet",
name="wallet",
)
await wallet.load_mint()
yield wallet
@pytest.mark.asyncio
async def test_db_tables(ledger: Ledger):
async with ledger.db.connect() as conn:
if ledger.db.type == db.SQLITE:
tables_res = await conn.execute(
"SELECT name FROM sqlite_master WHERE type='table';"
)
elif ledger.db.type in {db.POSTGRES, db.COCKROACH}:
tables_res = await conn.execute(
"SELECT table_name FROM information_schema.tables WHERE table_schema ="
" 'public';"
)
tables = [t[0] for t in tables_res.all()]
tables_expected = [
"dbversions",
"keysets",
"proofs_used",
"proofs_pending",
"melt_quotes",
"mint_quotes",
"mint_pubkeys",
"promises",
]
for table in tables_expected:
assert table in tables
@pytest.mark.asyncio
@@ -27,7 +93,7 @@ async def test_backup_db_migration(ledger: Ledger):
@pytest.mark.asyncio
async def test_timestamp_now(ledger: Ledger):
ts = timestamp_now(ledger.db)
ts = ledger.db.timestamp_now_str()
if ledger.db.type == db.SQLITE:
assert isinstance(ts, str)
assert int(ts) <= time.time()
@@ -37,33 +103,203 @@ async def test_timestamp_now(ledger: Ledger):
@pytest.mark.asyncio
async def test_get_connection(ledger: Ledger):
async def test_db_connect(ledger: Ledger):
async with ledger.db.connect() as conn:
assert isinstance(conn, Connection)
@pytest.mark.asyncio
async def test_db_tables(ledger: Ledger):
async with ledger.db.connect() as conn:
if ledger.db.type == db.SQLITE:
tables_res = await conn.execute(
"SELECT name FROM sqlite_master WHERE type='table';"
)
elif ledger.db.type in {db.POSTGRES, db.COCKROACH}:
tables_res = await conn.execute(
"SELECT table_name FROM information_schema.tables WHERE table_schema ="
" 'public';"
)
tables = [t[0] for t in await tables_res.fetchall()]
tables_expected = [
"dbversions",
"keysets",
"proofs_used",
"proofs_pending",
"melt_quotes",
"mint_quotes",
"mint_pubkeys",
"promises",
]
for table in tables_expected:
assert table in tables
async def test_db_get_connection(ledger: Ledger):
async with ledger.db.get_connection() as conn:
assert isinstance(conn, Connection)
# @pytest.mark.asyncio
# async def test_db_get_connection_locked(wallet: Wallet, ledger: Ledger):
# invoice = 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"):
# try:
# async with ledger.db.get_connection(
# lock_table="mint_quotes", lock_timeout=0.1
# ) 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);"
# )
# except Exception as exc:
# # this is expected to raise
# raise Exception(f"conn2: {str(exc)}")
# except Exception as exc:
# if str(exc).startswith("conn2"):
# raise exc
# else:
# raise Exception("not expected to happen")
# await assert_err(get_connection(), "failed to acquire database lock")
@pytest.mark.asyncio
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)
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_timeout=0.1,
) as conn1:
await conn1.execute(
f"UPDATE mint_quotes SET amount=100 WHERE quote='{invoice.id}';"
)
try:
async with ledger.db.get_connection(
lock_table="mint_quotes",
lock_select_statement=f"quote='{invoice.id}'",
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}';"
)
except Exception as exc:
# this is expected to raise
raise Exception(f"conn2: {str(exc)}")
except Exception as exc:
if "conn2" in str(exc):
raise exc
else:
raise Exception(f"not expected to happen: {str(exc)}")
await assert_err(get_connection(), "failed to acquire database lock")
@pytest.mark.asyncio
async def test_db_set_proofs_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)
assert wallet.balance == 64
await assert_err_multiple(
asyncio.gather(
ledger.db_write._set_proofs_pending(wallet.proofs),
ledger.db_write._set_proofs_pending(wallet.proofs),
),
[
"failed to acquire database lock",
"proofs are pending",
], # depending on how fast the database is, it can be either
)
@pytest.mark.asyncio
async def test_db_set_proofs_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)
assert wallet.balance == 64
async def delayed_set_proofs_pending():
await asyncio.sleep(0.1)
await ledger.db_write._set_proofs_pending(wallet.proofs)
await assert_err(
asyncio.gather(
ledger.db_write._set_proofs_pending(wallet.proofs),
delayed_set_proofs_pending(),
),
"proofs are pending",
)
@pytest.mark.asyncio
async def test_db_set_proofs_pending_no_race_condition_different_proofs(
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])
assert wallet.balance == 64
assert len(wallet.proofs) == 2
asyncio.gather(
ledger.db_write._set_proofs_pending(wallet.proofs[:1]),
ledger.db_write._set_proofs_pending(wallet.proofs[1:]),
)
@pytest.mark.asyncio
async def test_db_get_connection_lock_different_row(wallet: Wallet, ledger: Ledger):
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)
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_timeout=0.1,
):
try:
async with ledger.db.get_connection(
lock_table="mint_quotes",
lock_select_statement=f"quote='{invoice2.id}'",
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
)
assert quote is not None
quote.amount = 100
await ledger.crud.update_mint_quote(
quote=quote, db=ledger.db, conn=conn2
)
except Exception as exc:
# this is expected to raise
raise Exception(f"conn2: {str(exc)}")
except Exception as exc:
if "conn2" in str(exc):
raise exc
else:
raise Exception(f"not expected to happen: {str(exc)}")
await get_connection2()
@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)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64
async with ledger.db.connect(lock_table="proofs_pending", lock_timeout=0.1) as conn:
assert isinstance(conn, Connection)
await assert_err(
ledger.db_write._set_proofs_pending(wallet.proofs),
"failed to acquire database lock",
)

View File

@@ -69,7 +69,7 @@ async def test_get_keyset(ledger: Ledger):
@pytest.mark.asyncio
async def test_mint(ledger: Ledger):
quote = await ledger.mint_quote(PostMintQuoteRequest(amount=8, unit="sat"))
pay_if_regtest(quote.request)
await pay_if_regtest(quote.request)
blinded_messages_mock = [
BlindedMessage(
amount=8,
@@ -89,7 +89,7 @@ async def test_mint(ledger: Ledger):
@pytest.mark.asyncio
async def test_mint_invalid_blinded_message(ledger: Ledger):
quote = await ledger.mint_quote(PostMintQuoteRequest(amount=8, unit="sat"))
pay_if_regtest(quote.request)
await pay_if_regtest(quote.request)
blinded_messages_mock_invalid_key = [
BlindedMessage(
amount=8,

View File

@@ -153,7 +153,7 @@ async def test_api_keyset_keys_old_keyset_id(ledger: Ledger):
)
async def test_split(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64
secrets, rs, derivation_paths = await wallet.generate_n_secrets(2)
@@ -162,7 +162,7 @@ async def test_split(ledger: Ledger, wallet: Wallet):
inputs_payload = [p.to_dict() for p in wallet.proofs]
outputs_payload = [o.dict() for o in outputs]
payload = {"inputs": inputs_payload, "outputs": outputs_payload}
response = httpx.post(f"{BASE_URL}/v1/swap", json=payload)
response = httpx.post(f"{BASE_URL}/v1/swap", json=payload, timeout=None)
assert response.status_code == 200, f"{response.url} {response.status_code}"
result = response.json()
assert len(result["signatures"]) == 2
@@ -208,7 +208,7 @@ async def test_mint_quote(ledger: Ledger):
assert result["expiry"] == expiry
# pay the invoice
pay_if_regtest(result["request"])
await pay_if_regtest(result["request"])
# get mint quote again from api
response = httpx.get(
@@ -234,7 +234,7 @@ async def test_mint_quote(ledger: Ledger):
)
async def test_mint(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
quote_id = invoice.id
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(10000, 10001)
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
@@ -352,7 +352,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64
@@ -411,7 +411,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64
@@ -439,6 +439,7 @@ async def test_melt_external(ledger: Ledger, wallet: Wallet):
},
timeout=None,
)
response.raise_for_status()
assert response.status_code == 200, f"{response.url} {response.status_code}"
result = response.json()
assert result.get("payment_preimage") is not None
@@ -486,7 +487,7 @@ async def test_api_check_state(ledger: Ledger):
)
async def test_api_restore(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64
secret_counter = await bump_secret_derivation(

View File

@@ -67,7 +67,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(20000, 20001)
@@ -88,7 +88,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(80000, 80001)
@@ -124,7 +124,7 @@ async def test_api_mint_validation(ledger):
@pytest.mark.asyncio
async def test_mint(ledger: Ledger, wallet: Wallet):
invoice = await wallet.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
quote_id = invoice.id
secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(10000, 10001)
outputs, rs = wallet._construct_outputs([32, 32], secrets, rs)
@@ -148,9 +148,9 @@ async def test_mint(ledger: Ledger, wallet: Wallet):
@pytest.mark.asyncio
async def test_melt_internal(ledger: Ledger, wallet: Wallet):
# internal invoice
# fill wallet
invoice = await wallet.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64
@@ -190,15 +190,13 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64
# create invoice to melt to
invoice = await wallet.request_mint(64)
invoice_payment_request = invoice.bolt11
quote = await wallet.melt_quote(invoice_payment_request)
assert quote.amount == 64
assert quote.fee_reserve == 0
@@ -231,7 +229,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64
@@ -325,7 +323,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64
secret_counter = await bump_secret_derivation(

View File

@@ -1,23 +1,18 @@
import pytest
import pytest_asyncio
from cashu.core.base import MeltQuoteState, MintQuoteState, ProofSpentState
from cashu.core.models import PostMeltQuoteRequest
from cashu.mint.ledger import Ledger
from cashu.wallet.wallet import Wallet
from cashu.wallet.wallet import Wallet as Wallet1
from tests.conftest import SERVER_ENDPOINT
from tests.helpers import is_postgres
async def assert_err(f, msg):
"""Compute f() and expect an error message 'msg'."""
try:
await f
except Exception as exc:
if msg not in str(exc.args[0]):
raise Exception(f"Expected error: {msg}, got: {exc.args[0]}")
return
raise Exception(f"Expected error: {msg}, got no error")
from tests.helpers import (
assert_err,
is_github_actions,
is_postgres,
pay_if_regtest,
)
@pytest_asyncio.fixture(scope="function")
@@ -31,6 +26,35 @@ async def wallet1(ledger: Ledger):
yield wallet1
@pytest.mark.asyncio
@pytest.mark.skipif(is_github_actions, reason="GITHUB_ACTIONS")
async def test_mint_proofs_pending(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(64)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
proofs = wallet1.proofs.copy()
proofs_states_before_split = await wallet1.check_proof_state(proofs)
assert all(
[s.state == ProofSpentState.unspent for s in proofs_states_before_split.states]
)
await ledger.db_write._set_proofs_pending(proofs)
proof_states = await wallet1.check_proof_state(proofs)
assert all([s.state == ProofSpentState.pending for s in proof_states.states])
await assert_err(wallet1.split(wallet1.proofs, 20), "proofs are pending.")
await ledger.db_write._unset_proofs_pending(proofs)
await wallet1.split(proofs, 20)
proofs_states_after_split = await wallet1.check_proof_state(proofs)
assert all(
[s.state == ProofSpentState.spent for s in proofs_states_after_split.states]
)
@pytest.mark.asyncio
async def test_mint_quote(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(128)
@@ -42,10 +66,63 @@ async def test_mint_quote(wallet1: Wallet, ledger: Ledger):
assert quote.unit == "sat"
assert not quote.paid
assert quote.checking_id == invoice.payment_hash
assert quote.paid_time is None
# assert quote.paid_time is None
assert quote.created_time
@pytest.mark.asyncio
async def test_mint_quote_state_transitions(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.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.quote == invoice.id
assert quote.state == MintQuoteState.unpaid
# set pending again
async def set_state(quote, state):
quote.state = state
# set pending
await assert_err(
set_state(quote, MintQuoteState.pending),
"Cannot change state of an unpaid mint quote",
)
# set unpaid
await assert_err(
set_state(quote, MintQuoteState.unpaid),
"Cannot change state of an unpaid mint quote",
)
# set paid
quote.state = MintQuoteState.paid
# set unpaid
await assert_err(
set_state(quote, MintQuoteState.unpaid),
"Cannot change state of a paid mint quote to unpaid.",
)
# set pending
quote.state = MintQuoteState.pending
# set paid again
quote.state = MintQuoteState.paid
# set pending again
quote.state = MintQuoteState.pending
# set issued
quote.state = MintQuoteState.issued
# set pending again
await assert_err(
set_state(quote, MintQuoteState.pending),
"Cannot change state of an issued mint quote.",
)
@pytest.mark.asyncio
async def test_get_mint_quote_by_request(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(128)
@@ -56,7 +133,7 @@ async def test_get_mint_quote_by_request(wallet1: Wallet, ledger: Ledger):
assert quote.amount == 128
assert quote.unit == "sat"
assert not quote.paid
assert quote.paid_time is None
# assert quote.paid_time is None
assert quote.created_time
@@ -74,10 +151,112 @@ async def test_melt_quote(wallet1: Wallet, ledger: Ledger):
assert quote.unit == "sat"
assert not quote.paid
assert quote.checking_id == invoice.payment_hash
assert quote.paid_time is None
# assert quote.paid_time is None
assert quote.created_time
@pytest.mark.asyncio
async def test_melt_quote_set_pending(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(128)
assert invoice is not None
melt_quote = await ledger.melt_quote(
PostMeltQuoteRequest(request=invoice.bolt11, unit="sat")
)
assert melt_quote is not None
assert melt_quote.state == MeltQuoteState.unpaid.value
quote = await ledger.crud.get_melt_quote(quote_id=melt_quote.quote, db=ledger.db)
assert quote is not None
assert quote.quote == melt_quote.quote
assert quote.state == MeltQuoteState.unpaid
previous_state = quote.state
await ledger.db_write._set_melt_quote_pending(quote)
quote = await ledger.crud.get_melt_quote(quote_id=melt_quote.quote, db=ledger.db)
assert quote is not None
assert quote.state == MeltQuoteState.pending
# set unpending
await ledger.db_write._unset_melt_quote_pending(quote, previous_state)
quote = await ledger.crud.get_melt_quote(quote_id=melt_quote.quote, db=ledger.db)
assert quote is not None
assert quote.state == previous_state
@pytest.mark.asyncio
async def test_melt_quote_state_transitions(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(128)
assert invoice is not None
melt_quote = await ledger.melt_quote(
PostMeltQuoteRequest(request=invoice.bolt11, unit="sat")
)
quote = await ledger.crud.get_melt_quote(quote_id=melt_quote.quote, db=ledger.db)
assert quote is not None
assert quote.quote == melt_quote.quote
assert quote.state == MeltQuoteState.unpaid
# set pending
quote.state = MeltQuoteState.pending
# set unpaid
quote.state = MeltQuoteState.unpaid
# set paid
quote.state = MeltQuoteState.paid
# set pending again
async def set_state(quote, state):
quote.state = state
await assert_err(
set_state(quote, MeltQuoteState.pending),
"Cannot change state of a paid melt quote.",
)
@pytest.mark.asyncio
async def test_mint_quote_set_pending(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.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.state == MintQuoteState.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)
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
assert quote is not None
assert quote.state == MintQuoteState.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)
assert quote is not None
assert quote.state == MintQuoteState.pending
# try to mint while pending
await assert_err(wallet1.mint(128, id=invoice.id), "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)
assert quote is not None
assert quote.state == previous_state
assert quote.state == MintQuoteState.paid
# # set paid and mint again
# quote.state = MintQuoteState.paid
# await ledger.crud.update_mint_quote(quote=quote, db=ledger.db)
await wallet1.mint(quote.amount, id=quote.quote)
# check if quote is issued
quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db)
assert quote is not None
assert quote.state == MintQuoteState.issued
@pytest.mark.asyncio
@pytest.mark.skipif(not is_postgres, reason="only works with Postgres")
async def test_postgres_working():

View File

@@ -49,7 +49,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, split=[1] * 64, id=invoice.id)
# two proofs
@@ -115,7 +115,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10)
@@ -133,7 +133,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10)
@@ -151,7 +151,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10)
@@ -173,6 +173,7 @@ 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 pay_if_regtest(invoice.bolt11)
await wallet1.mint(128, id=invoice.id)
assert wallet1.balance == 128
@@ -217,7 +218,7 @@ async def test_melt_external_with_fees(wallet1: Wallet, ledger: Ledger):
# mint twice so we have enough to pay the second invoice back
invoice = await wallet1.request_mint(128)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(128, id=invoice.id)
assert wallet1.balance == 128

View File

@@ -241,7 +241,7 @@ async def test_startup_fakewallet_pending_quote_pending(ledger: Ledger):
async def test_startup_regtest_pending_quote_pending(wallet: Wallet, ledger: Ledger):
# fill wallet
invoice = await wallet.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64
@@ -286,7 +286,7 @@ async def test_startup_regtest_pending_quote_pending(wallet: Wallet, ledger: Led
async def test_startup_regtest_pending_quote_success(wallet: Wallet, ledger: Ledger):
# fill wallet
invoice = await wallet.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64
@@ -334,7 +334,7 @@ async def test_startup_regtest_pending_quote_failure(wallet: Wallet, ledger: Led
"""Simulate a failure to pay the hodl invoice by canceling it."""
# fill wallet
invoice = await wallet.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64

View File

@@ -1,6 +1,7 @@
import pytest
import pytest_asyncio
from cashu.core.base import MeltQuoteState, MintQuoteState
from cashu.core.helpers import sum_proofs
from cashu.core.models import PostMeltQuoteRequest, PostMintQuoteRequest
from cashu.mint.ledger import Ledger
@@ -37,7 +38,9 @@ async def wallet1(ledger: Ledger):
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 pay_if_regtest(invoice.bolt11)
await wallet1.mint(128, id=invoice.id)
await pay_if_regtest(invoice.bolt11)
assert wallet1.balance == 128
# create a mint quote so that we can melt to it internally
@@ -48,17 +51,21 @@ async def test_melt_internal(wallet1: Wallet, ledger: Ledger):
PostMeltQuoteRequest(request=invoice_payment_request, unit="sat")
)
assert not melt_quote.paid
assert melt_quote.state == MeltQuoteState.unpaid.value
assert melt_quote.amount == 64
assert melt_quote.fee_reserve == 0
melt_quote_pre_payment = await ledger.get_melt_quote(melt_quote.quote)
assert not melt_quote_pre_payment.paid, "melt quote should not be paid"
assert melt_quote_pre_payment.state == MeltQuoteState.unpaid
keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, 64)
await ledger.melt(proofs=send_proofs, quote=melt_quote.quote)
melt_quote_post_payment = await ledger.get_melt_quote(melt_quote.quote)
assert melt_quote_post_payment.paid, "melt quote should be paid"
assert melt_quote_post_payment.state == MeltQuoteState.paid
@pytest.mark.asyncio
@@ -66,7 +73,7 @@ async def test_melt_internal(wallet1: Wallet, ledger: Ledger):
async def test_melt_external(wallet1: Wallet, ledger: Ledger):
# mint twice so we have enough to pay the second invoice back
invoice = await wallet1.request_mint(128)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(128, id=invoice.id)
assert wallet1.balance == 128
@@ -74,6 +81,9 @@ async def test_melt_external(wallet1: Wallet, ledger: Ledger):
invoice_payment_request = invoice_dict["payment_request"]
mint_quote = await wallet1.melt_quote(invoice_payment_request)
assert not mint_quote.paid, "mint quote should not be paid"
assert mint_quote.state == MeltQuoteState.unpaid.value
total_amount = mint_quote.amount + mint_quote.fee_reserve
keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, total_amount)
melt_quote = await ledger.melt_quote(
@@ -82,22 +92,25 @@ async def test_melt_external(wallet1: Wallet, ledger: Ledger):
melt_quote_pre_payment = await ledger.get_melt_quote(melt_quote.quote)
assert not melt_quote_pre_payment.paid, "melt quote should not be paid"
assert melt_quote_pre_payment.state == MeltQuoteState.unpaid
assert not melt_quote.paid, "melt quote should not be paid"
await ledger.melt(proofs=send_proofs, quote=melt_quote.quote)
melt_quote_post_payment = await ledger.get_melt_quote(melt_quote.quote)
assert melt_quote_post_payment.paid, "melt quote should be paid"
assert melt_quote_post_payment.state == MeltQuoteState.paid
@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 pay_if_regtest(invoice.bolt11)
mint_quote = await ledger.get_mint_quote(invoice.id)
assert mint_quote.paid, "mint quote should be paid"
assert mint_quote.state == MintQuoteState.paid
output_amounts = [128]
secrets, rs, derivation_paths = await wallet1.generate_n_secrets(
@@ -111,24 +124,32 @@ async def test_mint_internal(wallet1: Wallet, ledger: Ledger):
"outputs have already been signed before.",
)
mint_quote_after_payment = await ledger.get_mint_quote(invoice.id)
assert mint_quote_after_payment.paid, "mint quote should be paid"
assert mint_quote_after_payment.state == MintQuoteState.issued
@pytest.mark.asyncio
@pytest.mark.skipif(is_fake, reason="only works with Regtest")
async def test_mint_external(wallet1: Wallet, ledger: Ledger):
quote = await ledger.mint_quote(PostMintQuoteRequest(amount=128, unit="sat"))
assert not quote.paid, "mint quote should not be paid"
assert quote.state == MintQuoteState.unpaid
mint_quote = await ledger.get_mint_quote(quote.quote)
assert not mint_quote.paid, "mint quote already paid"
assert mint_quote.state == MintQuoteState.unpaid
await assert_err(
wallet1.mint(128, id=quote.quote),
"quote not paid",
)
pay_if_regtest(quote.request)
await pay_if_regtest(quote.request)
mint_quote = await ledger.get_mint_quote(quote.quote)
assert mint_quote.paid, "mint quote should be paid"
assert mint_quote.state == MintQuoteState.paid
output_amounts = [128]
secrets, rs, derivation_paths = await wallet1.generate_n_secrets(
@@ -137,11 +158,15 @@ async def test_mint_external(wallet1: Wallet, ledger: Ledger):
outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs)
await ledger.mint(outputs=outputs, quote_id=quote.quote)
mint_quote_after_payment = await ledger.get_mint_quote(quote.quote)
assert mint_quote_after_payment.paid, "mint quote should be paid"
assert mint_quote_after_payment.state == MintQuoteState.issued
@pytest.mark.asyncio
async def test_split(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, 10)
@@ -158,7 +183,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 10, set_reserved=False)
await assert_err(
@@ -170,7 +195,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
keep_proofs, send_proofs = await wallet1.split_to_send(
@@ -199,7 +224,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(128, id=invoice.id)
inputs = wallet1.proofs
@@ -223,7 +248,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(128, split=[64, 64], id=invoice.id)
inputs1 = wallet1.proofs[:1]
inputs2 = wallet1.proofs[1:]
@@ -258,7 +283,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
output_amounts = [128]
secrets, rs, derivation_paths = await wallet1.generate_n_secrets(
len(output_amounts)
@@ -268,7 +293,7 @@ async def test_mint_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
# now try to mint with the same outputs again
invoice2 = await wallet1.request_mint(128)
pay_if_regtest(invoice2.bolt11)
await pay_if_regtest(invoice2.bolt11)
await assert_err(
ledger.mint(outputs=outputs, quote_id=invoice2.id),
@@ -279,7 +304,7 @@ async def test_mint_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
@pytest.mark.asyncio
async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(130)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(130, id=invoice.id)
output_amounts = [128]
@@ -290,7 +315,7 @@ async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger):
# we use the outputs once for minting
invoice2 = await wallet1.request_mint(128)
pay_if_regtest(invoice2.bolt11)
await pay_if_regtest(invoice2.bolt11)
await ledger.mint(outputs=outputs, quote_id=invoice2.id)
# use the same outputs for melting
@@ -307,7 +332,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(32, id=invoice.id)
# outputs for fee return
@@ -336,7 +361,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(130, split=[64, 64, 2], id=invoice.id)
# outputs for fee return
@@ -368,7 +393,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, 10)
@@ -385,7 +410,7 @@ async def test_check_proof_state(wallet1: Wallet, ledger: Ledger):
# f"ws://localhost:{SERVER_PORT}/v1/quote/{invoice.id}"
# )
# await asyncio.sleep(0.1)
# pay_if_regtest(invoice.bolt11)
# await pay_if_regtest(invoice.bolt11)
# await wallet1.mint(64, id=invoice.id)
# await asyncio.sleep(0.1)
# data = str(ws.recv())

View File

@@ -32,7 +32,7 @@ async def wallet():
async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger):
# fill wallet
invoice = await wallet.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64

View File

@@ -40,6 +40,18 @@ async def assert_err(f, msg: Union[str, CashuError]):
raise Exception(f"Expected error: {msg}, got no error")
async def assert_err_multiple(f, msgs: List[str]):
"""Compute f() and expect an error message 'msg'."""
try:
await f
except Exception as exc:
for msg in msgs:
if msg in str(exc.args[0]):
return
raise Exception(f"Expected error: {msgs}, got: {exc.args[0]}")
raise Exception(f"Expected error: {msgs}, got no error")
def assert_amt(proofs: List[Proof], expected: int):
"""Assert amounts the proofs contain."""
assert sum([p.amount for p in proofs]) == expected
@@ -155,7 +167,7 @@ async def test_request_mint(wallet1: Wallet):
@pytest.mark.asyncio
async def test_mint(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
expected_proof_amounts = wallet1.split_wallet_state(64)
await wallet1.mint(64, id=invoice.id)
assert wallet1.balance == 64
@@ -179,7 +191,7 @@ 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))
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(amount=sum(amts), split=amts, id=invoice.id)
assert wallet1.balance == 27
assert wallet1.proof_amounts == amts
@@ -211,7 +223,7 @@ async def test_mint_amounts_wrong_order(wallet1: Wallet):
@pytest.mark.asyncio
async def test_split(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
assert wallet1.balance == 64
# the outputs we keep that we expect after the split
@@ -231,7 +243,7 @@ async def test_split(wallet1: Wallet):
@pytest.mark.asyncio
async def test_split_to_send(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
assert wallet1.balance == 64
@@ -253,7 +265,7 @@ async def test_split_to_send(wallet1: Wallet):
@pytest.mark.asyncio
async def test_split_more_than_balance(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
await assert_err(
wallet1.split(wallet1.proofs, 128),
@@ -267,7 +279,7 @@ async def test_split_more_than_balance(wallet1: Wallet):
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)
pay_if_regtest(topup_invoice.bolt11)
await pay_if_regtest(topup_invoice.bolt11)
await wallet1.mint(128, id=topup_invoice.id)
assert wallet1.balance == 128
@@ -333,7 +345,7 @@ async def test_melt(wallet1: Wallet):
@pytest.mark.asyncio
async def test_split_to_send_more_than_balance(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
await assert_err(
wallet1.split_to_send(wallet1.proofs, 128, set_reserved=True),
@@ -346,7 +358,7 @@ async def test_split_to_send_more_than_balance(wallet1: Wallet):
@pytest.mark.asyncio
async def test_double_spend(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
doublespend = await wallet1.mint(64, id=invoice.id)
await wallet1.split(wallet1.proofs, 20)
await assert_err(
@@ -360,7 +372,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
doublespend = await wallet1.mint(64, id=invoice.id)
await assert_err(
wallet1.split(wallet1.proofs + doublespend, 20),
@@ -374,24 +386,24 @@ async def test_duplicate_proofs_double_spent(wallet1: Wallet):
@pytest.mark.skipif(is_github_actions, reason="GITHUB_ACTIONS")
async def test_split_race_condition(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
# run two splits in parallel
import asyncio
await assert_err(
await assert_err_multiple(
asyncio.gather(
wallet1.split(wallet1.proofs, 20),
wallet1.split(wallet1.proofs, 20),
),
"proofs are pending.",
["proofs are pending.", "already spent."],
)
@pytest.mark.asyncio
async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
_, spendable_proofs = await wallet1.split_to_send(
wallet1.proofs, 32, set_reserved=True
@@ -410,7 +422,7 @@ async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet):
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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
await wallet1.invalidate(wallet1.proofs)
assert wallet1.balance == 0
@@ -420,7 +432,7 @@ async def test_invalidate_all_proofs(wallet1: Wallet):
async def test_invalidate_unspent_proofs_with_checking(wallet1: Wallet):
"""Try to invalidate proofs that have not been spent yet but force no check."""
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
await wallet1.invalidate(wallet1.proofs, check_spendable=True)
assert wallet1.balance == 64
@@ -429,7 +441,7 @@ async def test_invalidate_unspent_proofs_with_checking(wallet1: Wallet):
@pytest.mark.asyncio
async def test_split_invalid_amount(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
await assert_err(
wallet1.split(wallet1.proofs, -1),
@@ -440,7 +452,7 @@ async def test_split_invalid_amount(wallet1: Wallet):
@pytest.mark.asyncio
async def test_token_state(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
assert wallet1.balance == 64
resp = await wallet1.check_proof_state(wallet1.proofs)

View File

@@ -117,7 +117,7 @@ def test_invoice_return_immediately(mint, cli_prefix):
assert result.exception is None
invoice, invoice_id = get_bolt11_and_invoice_id_from_invoice_command(result.output)
pay_if_regtest(invoice)
asyncio.run(pay_if_regtest(invoice))
result = runner.invoke(
cli,
@@ -146,7 +146,7 @@ def test_invoice_with_split(mint, cli_prefix):
assert result.exception is None
invoice, invoice_id = get_bolt11_and_invoice_id_from_invoice_command(result.output)
pay_if_regtest(invoice)
asyncio.run(pay_if_regtest(invoice))
result = runner.invoke(
cli,
[*cli_prefix, "invoice", "10", "-s", "1", "--id", invoice_id],
@@ -164,7 +164,7 @@ def test_invoices_with_minting(cli_prefix):
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))
# act
runner = CliRunner()
result = runner.invoke(

View File

@@ -58,7 +58,7 @@ async def wallet2():
@pytest.mark.asyncio
async def test_create_htlc_secret(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
preimage = "00000000000000000000000000000000"
preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
@@ -69,7 +69,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
preimage = "00000000000000000000000000000000"
preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
@@ -82,7 +82,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
preimage = "00000000000000000000000000000000"
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
@@ -96,7 +96,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
preimage = "00000000000000000000000000000000"
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
@@ -114,7 +114,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
@@ -134,7 +134,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
@@ -158,7 +158,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
@@ -180,7 +180,7 @@ async def test_htlc_redeem_hashlock_wrong_signature_timelock_correct_signature(
wallet1: Wallet, wallet2: Wallet
):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
@@ -214,7 +214,7 @@ async def test_htlc_redeem_hashlock_wrong_signature_timelock_wrong_signature(
wallet1: Wallet, wallet2: Wallet
):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
preimage = "00000000000000000000000000000000"
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()

View File

@@ -78,7 +78,7 @@ async def test_check_invoice_external(wallet: LightningWallet):
assert invoice.checking_id
status = await wallet.get_invoice_status(invoice.checking_id)
assert not status.paid
pay_if_regtest(invoice.payment_request)
await pay_if_regtest(invoice.payment_request)
status = await wallet.get_invoice_status(invoice.checking_id)
assert status.paid
@@ -113,7 +113,7 @@ async def test_pay_invoice_external(wallet: LightningWallet):
invoice = await wallet.create_invoice(64)
assert invoice.payment_request
assert invoice.checking_id
pay_if_regtest(invoice.payment_request)
await pay_if_regtest(invoice.payment_request)
status = await wallet.get_invoice_status(invoice.checking_id)
assert status.paid
assert wallet.available_balance >= 64

View File

@@ -60,7 +60,7 @@ async def wallet2():
@pytest.mark.asyncio
async def test_create_p2pk_pubkey(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
pubkey = await wallet1.create_p2pk_pubkey()
PublicKey(bytes.fromhex(pubkey), raw=True)
@@ -69,7 +69,7 @@ async def test_create_p2pk_pubkey(wallet1: Wallet):
@pytest.mark.asyncio
async def test_p2pk(wallet1: Wallet, wallet2: Wallet):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
# p2pk test
@@ -93,7 +93,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
# p2pk test
@@ -109,7 +109,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side
# sender side
@@ -130,7 +130,7 @@ async def test_p2pk_short_locktime_receive_with_wrong_private_key(
wallet1: Wallet, wallet2: Wallet
):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side
# sender side
@@ -156,7 +156,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side
# sender side
@@ -185,7 +185,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
await wallet2.create_p2pk_pubkey() # receiver side
# sender side
@@ -221,7 +221,7 @@ async def test_p2pk_locktime_with_second_refund_pubkey(
wallet1: Wallet, wallet2: Wallet
):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
pubkey_wallet1 = await wallet1.create_p2pk_pubkey() # receiver side
pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side
@@ -253,7 +253,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
@@ -275,7 +275,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
@@ -299,7 +299,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
@@ -320,7 +320,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
pubkey_wallet1 = await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
@@ -345,7 +345,7 @@ 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)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
# p2pk test
@@ -363,7 +363,7 @@ async def test_p2pk_multisig_with_wrong_first_private_key(
wallet1: Wallet, wallet2: Wallet
):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
await wallet1.create_p2pk_pubkey()
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()

View File

@@ -34,7 +34,7 @@ async def wallet():
async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger):
# fill wallet
invoice = await wallet.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64
@@ -72,7 +72,7 @@ async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger):
async def test_regtest_failed_quote(wallet: Wallet, ledger: Ledger):
# fill wallet
invoice = await wallet.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
assert wallet.balance == 64

View File

@@ -38,12 +38,12 @@ async def test_regtest_pay_mpp(wallet: Wallet, ledger: Ledger):
# top up wallet twice so we have enough for two payments
topup_invoice = await wallet.request_mint(128)
pay_if_regtest(topup_invoice.bolt11)
await pay_if_regtest(topup_invoice.bolt11)
proofs1 = await wallet.mint(128, id=topup_invoice.id)
assert wallet.balance == 128
topup_invoice = await wallet.request_mint(128)
pay_if_regtest(topup_invoice.bolt11)
await pay_if_regtest(topup_invoice.bolt11)
proofs2 = await wallet.mint(128, id=topup_invoice.id)
assert wallet.balance == 256
@@ -82,17 +82,17 @@ async def test_regtest_pay_mpp_incomplete_payment(wallet: Wallet, ledger: Ledger
# top up wallet twice so we have enough for three payments
topup_invoice = await wallet.request_mint(128)
pay_if_regtest(topup_invoice.bolt11)
await pay_if_regtest(topup_invoice.bolt11)
proofs1 = await wallet.mint(128, id=topup_invoice.id)
assert wallet.balance == 128
topup_invoice = await wallet.request_mint(128)
pay_if_regtest(topup_invoice.bolt11)
await pay_if_regtest(topup_invoice.bolt11)
proofs2 = await wallet.mint(128, id=topup_invoice.id)
assert wallet.balance == 256
topup_invoice = await wallet.request_mint(128)
pay_if_regtest(topup_invoice.bolt11)
await pay_if_regtest(topup_invoice.bolt11)
proofs3 = await wallet.mint(128, id=topup_invoice.id)
assert wallet.balance == 384

View File

@@ -157,7 +157,7 @@ async def test_generate_secrets_from_to(wallet3: Wallet):
async def test_restore_wallet_after_mint(wallet3: Wallet):
await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet3.mint(64, id=invoice.id)
assert wallet3.balance == 64
await reset_wallet_db(wallet3)
@@ -193,7 +193,7 @@ async def test_restore_wallet_after_split_to_send(wallet3: Wallet):
await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet3.mint(64, id=invoice.id)
assert wallet3.balance == 64
@@ -218,7 +218,7 @@ async def test_restore_wallet_after_send_and_receive(wallet3: Wallet, wallet2: W
)
await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet3.mint(64, id=invoice.id)
assert wallet3.balance == 64
@@ -261,7 +261,7 @@ async def test_restore_wallet_after_send_and_self_receive(wallet3: Wallet):
await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet3.mint(64, id=invoice.id)
assert wallet3.balance == 64
@@ -290,7 +290,7 @@ async def test_restore_wallet_after_send_twice(
await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(2)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet3.mint(2, id=invoice.id)
box.add(wallet3.proofs)
assert wallet3.balance == 2
@@ -349,7 +349,7 @@ async def test_restore_wallet_after_send_and_self_receive_nonquadratic_value(
await reset_wallet_db(wallet3)
invoice = await wallet3.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet3.mint(64, id=invoice.id)
box.add(wallet3.proofs)
assert wallet3.balance == 64

View File

@@ -47,7 +47,7 @@ async def test_wallet_subscription_mint(wallet: Wallet):
asyncio.run(wallet.mint(int(invoice.amount), id=invoice.id))
invoice, sub = await wallet.request_mint_with_callback(128, callback=callback)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
wait = settings.fakewallet_delay_incoming_payment or 2
await asyncio.sleep(wait + 2)
@@ -70,7 +70,7 @@ async def test_wallet_subscription_swap(wallet: Wallet):
pytest.skip("No websocket support")
invoice = await wallet.request_mint(64)
pay_if_regtest(invoice.bolt11)
await pay_if_regtest(invoice.bolt11)
await wallet.mint(64, id=invoice.id)
triggered = False