Skip to content

Commit

Permalink
tests succeed with lndrestwallet
Browse files Browse the repository at this point in the history
  • Loading branch information
callebtc committed Nov 15, 2023
1 parent d5c4286 commit fe2ea08
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 33 deletions.
7 changes: 3 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,16 @@ package:
test:
PYTHONUNBUFFERED=1 \
DEBUG=true \
MINT_LIGHTNING_BACKEND=FakeWallet \
poetry run pytest tests --cov-report xml --cov cashu

test-lndrest:
PYTHONUNBUFFERED=1 \
DEBUG=true \
MINT_LIGHTNING_BACKEND=LndRestWallet \
MINT_LND_REST_ENDPOINT=https://localhost:8081/ \
MINT_LND_REST_CERT=../legend-regtest-enviroment/data/lnd-3/tls.cert \
MINT_LND_REST_MACAROON=../legend-regtest-enviroment/data/lnd-3/data/chain/bitcoin/regtest/admin.macaroon \
poetry run pytest tests/test_wallet.py --cov-report xml --cov cashu
MINT_LND_REST_CERT=../cashu-regtest-enviroment/data/lnd-3/tls.cert \
MINT_LND_REST_MACAROON=../cashu-regtest-enviroment/data/lnd-3/data/chain/bitcoin/regtest/admin.macaroon \
poetry run pytest tests/test_cli.py --cov-report xml --cov cashu

install:
make clean
Expand Down
16 changes: 13 additions & 3 deletions cashu/wallet/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,17 @@ async def pay(ctx: Context, invoice: str, yes: bool):
help="Split minted tokens with a specific amount.",
type=int,
)
@click.option(
"--no-check",
"-n",
default=False,
is_flag=True,
help="Do not check if invoice is paid.",
type=bool,
)
@click.pass_context
@coro
async def invoice(ctx: Context, amount: int, id: str, split: int):
async def invoice(ctx: Context, amount: int, id: str, split: int, no_check: bool):
wallet: Wallet = ctx.obj["WALLET"]
await wallet.load_mint()
wallet.status()
Expand All @@ -236,9 +244,11 @@ async def invoice(ctx: Context, amount: int, id: str, split: int):
print(f"Invoice: {invoice.bolt11}")
print("")
print(
"If you abort this you can use this command to recheck the"
f" invoice:\ncashu invoice {amount} --id {invoice.id}"
"You can use this command to check the invoice: cashu invoice"
f" {amount} --id {invoice.id}"
)
if no_check:
return
check_until = time.time() + 5 * 60 # check for five minutes
print("")
print(
Expand Down
5 changes: 5 additions & 0 deletions tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,8 @@ def pay_onchain(address: str, sats: int) -> str:
# # FIXME: do this once mock data is removed from test data folder
# # os.remove(settings.lnbits_data_folder + "/database.sqlite3")
# pass


def pay_if_regtest(bolt11: str):
if is_regtest:
pay_real_invoice(bolt11)
65 changes: 59 additions & 6 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,24 @@
from cashu.core.settings import settings
from cashu.wallet.cli.cli import cli
from cashu.wallet.wallet import Wallet
from tests.helpers import is_fake, pay_if_regtest


@pytest.fixture(autouse=True, scope="session")
def cli_prefix():
yield ["--wallet", "test_cli_wallet", "--host", settings.mint_url, "--tests"]


def get_bolt11_and_invoice_id_from_invoice_command(output: str) -> (str, str):
invoice = [
line.split(" ")[1] for line in output.split("\n") if line.startswith("Invoice")
][0]
invoice_id = [
line.split(" ")[-1] for line in output.split("\n") if line.startswith("You can")
][0]
return invoice, invoice_id


async def init_wallet():
wallet = await Wallet.with_db(
url=settings.mint_host,
Expand Down Expand Up @@ -77,17 +88,42 @@ def test_balance(cli_prefix):
assert result.exit_code == 0


def test_invoice(mint, cli_prefix):
@pytest.mark.skipif(not is_fake, reason="only on fakewallet")
def test_invoice_automatic_fakewallet(mint, cli_prefix):
runner = CliRunner()
result = runner.invoke(
cli,
[*cli_prefix, "invoice", "1000"],
[*cli_prefix, "invoice", "-n", "1000"],
)
assert result.exception is None
print("INVOICE")
print(result.output)
wallet = asyncio.run(init_wallet())
# assert wallet.available_balance >= 1000
assert wallet.available_balance >= 1000
assert f"Balance: {wallet.available_balance} sat" in result.output
assert result.exit_code == 0


def test_invoice(mint, cli_prefix):
runner = CliRunner()
result = runner.invoke(
cli,
[*cli_prefix, "invoice", "-n", "1000"],
)

assert result.exception is None

invoice, invoice_id = get_bolt11_and_invoice_id_from_invoice_command(result.output)
pay_if_regtest(invoice)

result = runner.invoke(
cli,
[*cli_prefix, "invoice", "1000", "--id", invoice_id],
)
assert result.exception is None

wallet = asyncio.run(init_wallet())
assert wallet.available_balance >= 1000
assert f"Balance: {wallet.available_balance} sat" in result.output
assert result.exit_code == 0

Expand All @@ -96,11 +132,28 @@ def test_invoice_with_split(mint, cli_prefix):
runner = CliRunner()
result = runner.invoke(
cli,
[*cli_prefix, "invoice", "10", "-s", "1"],
[
*cli_prefix,
"invoice",
"10",
"-s",
"1",
"-n",
],
)
assert result.exception is None
# wallet = asyncio.run(init_wallet())
# assert wallet.proof_amounts.count(1) >= 10

invoice, invoice_id = get_bolt11_and_invoice_id_from_invoice_command(result.output)
pay_if_regtest(invoice)
result = runner.invoke(
cli,
[*cli_prefix, "invoice", "10", "-s", "1", "--id", invoice_id],
)
assert result.exception is None

assert result.exception is None
wallet = asyncio.run(init_wallet())
assert wallet.proof_amounts.count(1) >= 10


def test_wallets(cli_prefix):
Expand Down
5 changes: 5 additions & 0 deletions tests/test_mint_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from cashu.wallet.wallet import Wallet
from cashu.wallet.wallet import Wallet as Wallet1
from tests.conftest import SERVER_ENDPOINT
from tests.helpers import pay_if_regtest


@pytest_asyncio.fixture(scope="function")
Expand All @@ -23,8 +24,10 @@ async def wallet1(mint):
async def test_melt(wallet1: Wallet, ledger: Ledger):
# mint twice so we have enough to pay the second invoice back
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
assert wallet1.balance == 128
total_amount, fee_reserve_sat = await wallet1.get_pay_amount_with_fees(
Expand All @@ -41,6 +44,7 @@ async def test_melt(wallet1: Wallet, ledger: Ledger):
@pytest.mark.asyncio
async def test_split(wallet1: Wallet, ledger: Ledger):
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)

keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, 10)
Expand All @@ -57,6 +61,7 @@ async def test_split(wallet1: Wallet, ledger: Ledger):
@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 wallet1.mint(64, id=invoice.id)

keep_proofs, send_proofs = await wallet1.split_to_send(wallet1.proofs, 10)
Expand Down
54 changes: 34 additions & 20 deletions tests/test_wallet.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import asyncio
import shutil
from pathlib import Path
from typing import List, Union
Expand All @@ -15,7 +14,7 @@
from cashu.wallet.wallet import Wallet as Wallet1
from cashu.wallet.wallet import Wallet as Wallet2
from tests.conftest import SERVER_ENDPOINT
from tests.helpers import is_regtest, pay_real_invoice
from tests.helpers import get_real_invoice, is_regtest, pay_if_regtest


async def assert_err(f, msg: Union[str, CashuError]):
Expand Down Expand Up @@ -140,12 +139,7 @@ async def test_get_keyset_ids(wallet1: Wallet):
@pytest.mark.asyncio
async def test_mint(wallet1: Wallet):
invoice = await wallet1.request_mint(64)
if is_regtest:
await asyncio.sleep(2)
print("paying invoice in regtest...")
pay_real_invoice(invoice.bolt11)
print("Done")
await asyncio.sleep(5)
pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
assert wallet1.balance == 64

Expand All @@ -166,7 +160,7 @@ async def test_mint(wallet1: Wallet):
async def test_mint_amounts(wallet1: Wallet):
"""Mint predefined amounts"""
invoice = await wallet1.request_mint(64)

pay_if_regtest(invoice.bolt11)
amts = [1, 1, 1, 2, 2, 4, 16]
await wallet1.mint(amount=sum(amts), split=amts, id=invoice.id)
assert wallet1.balance == 27
Expand Down Expand Up @@ -196,6 +190,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 wallet1.mint(64, id=invoice.id)
assert wallet1.balance == 64
p1, p2 = await wallet1.split(wallet1.proofs, 20)
Expand All @@ -211,6 +206,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 wallet1.mint(64, id=invoice.id)
keep_proofs, spendable_proofs = await wallet1.split_to_send(
wallet1.proofs, 32, set_reserved=True
Expand All @@ -226,6 +222,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 wallet1.mint(64, id=invoice.id)
await assert_err(
wallet1.split(wallet1.proofs, 128),
Expand All @@ -239,8 +236,10 @@ 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
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
invoice = await wallet1.request_mint(64)
pay_if_regtest(invoice.bolt11)
await wallet1.mint(64, id=invoice.id)
assert wallet1.balance == 128

Expand All @@ -252,38 +251,46 @@ async def test_melt(wallet1: Wallet):
assert fee_reserve_sat == 2
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, total_amount)

invoice_to_pay = invoice.bolt11
invoice_payment_hash = str(invoice.payment_hash)
if is_regtest:
invoice_dict = get_real_invoice(64)
invoice_to_pay = invoice_dict["payment_request"]
invoice_payment_hash = str(invoice_dict["r_hash"])

melt_response = await wallet1.pay_lightning(
send_proofs, invoice=invoice.bolt11, fee_reserve_sat=fee_reserve_sat
send_proofs, invoice=invoice_to_pay, fee_reserve_sat=fee_reserve_sat
)

assert melt_response.change
assert len(melt_response.change) == 1
assert melt_response.change, "No change returned"
assert len(melt_response.change) == 1, "More than one change returned"
# NOTE: we assume that we will get a token back from the same keyset as the ones we melted
# this could be wrong if we melted tokens from an old keyset but the returned ones are
# from a newer one.
assert melt_response.change[0].id == send_proofs[0].id
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
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
db=wallet1.db, payment_hash=invoice_payment_hash, out=True
)
assert invoice_db
assert invoice_db, "No invoice in db"
proofs_used = await get_proofs(
db=wallet1.db, melt_id=invoice_db.id, table="proofs_used"
)

assert len(proofs_used) == len(send_proofs)
assert all([p.melt_id == invoice_db.id for p in 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"

# the payment was without fees so we need to remove it from the total amount
assert wallet1.balance == 128 - (total_amount - fee_reserve_sat)
assert wallet1.balance == 64
assert wallet1.balance == 128 - (total_amount - fee_reserve_sat), "Wrong balance"
assert wallet1.balance == 64, "Wrong balance"


@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 wallet1.mint(64, id=invoice.id)
await assert_err(
wallet1.split_to_send(wallet1.proofs, 128, set_reserved=True),
Expand All @@ -296,6 +303,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)
doublespend = await wallet1.mint(64, id=invoice.id)
await wallet1.split(wallet1.proofs, 20)
await assert_err(
Expand All @@ -309,6 +317,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)
doublespend = await wallet1.mint(64, id=invoice.id)
await assert_err(
wallet1.split(wallet1.proofs + doublespend, 20),
Expand All @@ -321,6 +330,7 @@ async def test_duplicate_proofs_double_spent(wallet1: Wallet):
@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 wallet1.mint(64, id=invoice.id)
_, spendable_proofs = await wallet1.split_to_send(
wallet1.proofs, 32, set_reserved=True
Expand All @@ -339,6 +349,7 @@ async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet):
async def test_invalidate_unspent_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 wallet1.mint(64, id=invoice.id)
await wallet1.invalidate(wallet1.proofs)
assert wallet1.balance == 64
Expand All @@ -348,6 +359,7 @@ async def test_invalidate_unspent_proofs(wallet1: Wallet):
async def test_invalidate_unspent_proofs_without_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 wallet1.mint(64, id=invoice.id)
await wallet1.invalidate(wallet1.proofs, check_spendable=False)
assert wallet1.balance == 0
Expand All @@ -356,6 +368,7 @@ async def test_invalidate_unspent_proofs_without_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 wallet1.mint(64, id=invoice.id)
await assert_err(
wallet1.split(wallet1.proofs, -1),
Expand All @@ -366,6 +379,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 wallet1.mint(64, id=invoice.id)
assert wallet1.balance == 64
resp = await wallet1.check_proof_state(wallet1.proofs)
Expand Down
Loading

0 comments on commit fe2ea08

Please sign in to comment.