mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-22 19:34:18 +01:00
* Update deprecated datetime * Add options to Invoices cli With these options, we are able to return: 1) all invoices (this is the default); 2) pending invoices (paid False, out False); 3) paid invoices; 4) and unpaid invoices. * make format * Fix mypy error with datetime * sort imports * Remove unneeded unit when printing out info * Fix wrong method doc * Try to mint pending invoices * make pre-commit * Refactor --tests flag to --mint The default will be false, i.e., if the user does not pass in the --mint flag, it will not try to mint the pending invoice. --------- Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
b8ad0e0a8f
commit
3b2f1aa6f4
@@ -255,9 +255,9 @@ class LedgerSpendingConditions:
|
||||
# check if all secrets are P2PK
|
||||
# NOTE: This is redundant, because P2PKSecret.from_secret() already checks for the kind
|
||||
# Leaving it in for explicitness
|
||||
if not all([
|
||||
SecretKind(secret.kind) == SecretKind.P2PK for secret in p2pk_secrets
|
||||
]):
|
||||
if not all(
|
||||
[SecretKind(secret.kind) == SecretKind.P2PK for secret in p2pk_secrets]
|
||||
):
|
||||
# not all secrets are P2PK
|
||||
return True
|
||||
|
||||
|
||||
@@ -3,24 +3,26 @@
|
||||
import asyncio
|
||||
import os
|
||||
import time
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from functools import wraps
|
||||
from itertools import groupby, islice
|
||||
from operator import itemgetter
|
||||
from os import listdir
|
||||
from os.path import isdir, join
|
||||
from typing import Optional
|
||||
|
||||
import click
|
||||
from click import Context
|
||||
from loguru import logger
|
||||
|
||||
from ...core.base import TokenV3, Unit
|
||||
from ...core.base import Invoice, TokenV3, Unit
|
||||
from ...core.helpers import sum_proofs
|
||||
from ...core.logging import configure_logger
|
||||
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_reserved_proofs,
|
||||
get_seed_and_mnemonic,
|
||||
@@ -124,7 +126,7 @@ async def cli(ctx: Context, host: str, walletname: str, unit: str, tests: bool):
|
||||
env_path = settings.env_file
|
||||
else:
|
||||
error_str += (
|
||||
"Ceate a new Cashu config file here:"
|
||||
"Create a new Cashu config file here:"
|
||||
f" {os.path.join(settings.cashu_dir, '.env')}"
|
||||
)
|
||||
env_path = os.path.join(settings.cashu_dir, ".env")
|
||||
@@ -158,7 +160,6 @@ async def cli(ctx: Context, host: str, walletname: str, unit: str, tests: bool):
|
||||
|
||||
assert wallet, "Wallet not found."
|
||||
ctx.obj["WALLET"] = wallet
|
||||
# await init_wallet(ctx.obj["WALLET"], load_proofs=False)
|
||||
|
||||
# only if a command is one of a subset that needs to specify a mint host
|
||||
# if a mint host is already specified as an argument `host`, use it
|
||||
@@ -166,7 +167,7 @@ async def cli(ctx: Context, host: str, walletname: str, unit: str, tests: bool):
|
||||
return
|
||||
# ------ MULTIUNIT ------- : Select a unit
|
||||
ctx.obj["WALLET"] = await get_unit_wallet(ctx)
|
||||
# ------ MUTLIMINT ------- : Select a wallet
|
||||
# ------ MULTIMINT ------- : Select a wallet
|
||||
# else: we ask the user to select one
|
||||
ctx.obj["WALLET"] = await get_mint_wallet(
|
||||
ctx
|
||||
@@ -637,8 +638,8 @@ async def pending(ctx: Context, legacy, number: int, offset: int):
|
||||
mint = [t.mint for t in tokenObj.token][0]
|
||||
# token_hidden_secret = await wallet.serialize_proofs(grouped_proofs)
|
||||
assert grouped_proofs[0].time_reserved
|
||||
reserved_date = datetime.utcfromtimestamp(
|
||||
int(grouped_proofs[0].time_reserved)
|
||||
reserved_date = datetime.fromtimestamp(
|
||||
int(grouped_proofs[0].time_reserved), timezone.utc
|
||||
).strftime("%Y-%m-%d %H:%M:%S")
|
||||
print(
|
||||
f"#{i} Amount:"
|
||||
@@ -692,39 +693,120 @@ async def locks(ctx):
|
||||
return True
|
||||
|
||||
|
||||
@cli.command("invoices", help="List of all pending invoices.")
|
||||
@cli.command("invoices", help="List of all invoices.")
|
||||
@click.option(
|
||||
"-op",
|
||||
"--only-paid",
|
||||
"paid",
|
||||
default=False,
|
||||
is_flag=True,
|
||||
help="Show only paid invoices.",
|
||||
type=bool,
|
||||
)
|
||||
@click.option(
|
||||
"-ou",
|
||||
"--only-unpaid",
|
||||
"unpaid",
|
||||
default=False,
|
||||
is_flag=True,
|
||||
help="Show only unpaid invoices.",
|
||||
type=bool,
|
||||
)
|
||||
@click.option(
|
||||
"-p",
|
||||
"--pending",
|
||||
"pending",
|
||||
default=False,
|
||||
is_flag=True,
|
||||
help="Show all pending invoices",
|
||||
type=bool,
|
||||
)
|
||||
@click.option(
|
||||
"--mint",
|
||||
"-m",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
help="Try to mint pending invoices",
|
||||
)
|
||||
@click.pass_context
|
||||
@coro
|
||||
async def invoices(ctx):
|
||||
async def invoices(ctx, paid: bool, unpaid: bool, pending: bool, mint: bool):
|
||||
wallet: Wallet = ctx.obj["WALLET"]
|
||||
invoices = await get_lightning_invoices(db=wallet.db)
|
||||
if len(invoices):
|
||||
print("")
|
||||
print("--------------------------\n")
|
||||
for invoice in invoices:
|
||||
|
||||
if paid and unpaid:
|
||||
print("You should only choose one option: either --only-paid or --only-unpaid")
|
||||
return
|
||||
|
||||
if mint:
|
||||
await wallet.load_mint()
|
||||
|
||||
paid_arg = None
|
||||
if unpaid:
|
||||
paid_arg = False
|
||||
elif paid:
|
||||
paid_arg = True
|
||||
|
||||
invoices = await get_lightning_invoices(
|
||||
db=wallet.db,
|
||||
paid=paid_arg,
|
||||
pending=pending or None,
|
||||
)
|
||||
|
||||
if len(invoices) == 0:
|
||||
print("No invoices found.")
|
||||
return
|
||||
|
||||
async def _try_to_mint_pending_invoice(amount: int, id: str) -> Optional[Invoice]:
|
||||
try:
|
||||
await wallet.mint(amount, id)
|
||||
return await get_lightning_invoice(db=wallet.db, id=id)
|
||||
except Exception as e:
|
||||
logger.error(f"Could not mint pending invoice [{id}]: {e}")
|
||||
return None
|
||||
|
||||
def _print_invoice_info(invoice: Invoice):
|
||||
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}")
|
||||
print(f"Amount: {abs(invoice.amount)}")
|
||||
if invoice.id:
|
||||
print(f"ID: {invoice.id}")
|
||||
|
||||
if invoice.preimage:
|
||||
print(f"Preimage: {invoice.preimage}")
|
||||
if invoice.time_created:
|
||||
d = datetime.utcfromtimestamp(
|
||||
int(float(invoice.time_created))
|
||||
d = datetime.fromtimestamp(
|
||||
int(float(invoice.time_created)), timezone.utc
|
||||
).strftime("%Y-%m-%d %H:%M:%S")
|
||||
print(f"Created: {d}")
|
||||
print(f"Created at: {d}")
|
||||
if invoice.time_paid:
|
||||
d = datetime.utcfromtimestamp(int(float(invoice.time_paid))).strftime(
|
||||
"%Y-%m-%d %H:%M:%S"
|
||||
d = datetime.fromtimestamp(
|
||||
(int(float(invoice.time_paid))), timezone.utc
|
||||
).strftime("%Y-%m-%d %H:%M:%S")
|
||||
print(f"Paid at: {d}")
|
||||
print(f"\nPayment request: {invoice.bolt11}")
|
||||
|
||||
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
|
||||
)
|
||||
print(f"Paid: {d}")
|
||||
print("")
|
||||
print(f"Payment request: {invoice.bolt11}")
|
||||
print("")
|
||||
print("--------------------------\n")
|
||||
else:
|
||||
# If the mint ran successfully and we are querying for pending or unpaid invoices, do not print it
|
||||
if pending or unpaid:
|
||||
continue
|
||||
# Otherwise, print the invoice with updated values
|
||||
if updated_invoice:
|
||||
invoice = updated_invoice
|
||||
|
||||
_print_invoice_info(invoice)
|
||||
invoices_printed_count += 1
|
||||
|
||||
if invoices_printed_count == 0:
|
||||
print("No invoices found.")
|
||||
else:
|
||||
print("\n--------------------------\n")
|
||||
|
||||
|
||||
@cli.command("wallets", help="List of all available wallets.")
|
||||
|
||||
@@ -67,10 +67,12 @@ async def get_reserved_proofs(
|
||||
db: Database,
|
||||
conn: Optional[Connection] = None,
|
||||
) -> List[Proof]:
|
||||
rows = await (conn or db).fetchall("""
|
||||
rows = await (conn or db).fetchall(
|
||||
"""
|
||||
SELECT * from proofs
|
||||
WHERE reserved
|
||||
""")
|
||||
"""
|
||||
)
|
||||
return [Proof.from_dict(dict(r)) for r in rows]
|
||||
|
||||
|
||||
@@ -279,15 +281,22 @@ async def get_lightning_invoice(
|
||||
async def get_lightning_invoices(
|
||||
db: Database,
|
||||
paid: Optional[bool] = None,
|
||||
pending: Optional[bool] = None,
|
||||
conn: Optional[Connection] = None,
|
||||
) -> List[Invoice]:
|
||||
clauses: List[Any] = []
|
||||
values: List[Any] = []
|
||||
|
||||
if paid is not None:
|
||||
if paid is not None and not pending:
|
||||
clauses.append("paid = ?")
|
||||
values.append(paid)
|
||||
|
||||
if pending:
|
||||
clauses.append("paid = ?")
|
||||
values.append(False)
|
||||
clauses.append("out = ?")
|
||||
values.append(False)
|
||||
|
||||
where = ""
|
||||
if clauses:
|
||||
where = f"WHERE {' AND '.join(clauses)}"
|
||||
|
||||
@@ -2,17 +2,20 @@ from ..core.db import Connection, Database
|
||||
|
||||
|
||||
async def m000_create_migrations_table(conn: Connection):
|
||||
await conn.execute("""
|
||||
await conn.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS dbversions (
|
||||
db TEXT PRIMARY KEY,
|
||||
version INT NOT NULL
|
||||
)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
async def m001_initial(db: Database):
|
||||
async with db.connect() as conn:
|
||||
await conn.execute(f"""
|
||||
await conn.execute(
|
||||
f"""
|
||||
CREATE TABLE IF NOT EXISTS proofs (
|
||||
amount {db.big_int} NOT NULL,
|
||||
C TEXT NOT NULL,
|
||||
@@ -21,9 +24,11 @@ async def m001_initial(db: Database):
|
||||
UNIQUE (secret)
|
||||
|
||||
);
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
await conn.execute(f"""
|
||||
await conn.execute(
|
||||
f"""
|
||||
CREATE TABLE IF NOT EXISTS proofs_used (
|
||||
amount {db.big_int} NOT NULL,
|
||||
C TEXT NOT NULL,
|
||||
@@ -32,25 +37,30 @@ async def m001_initial(db: Database):
|
||||
UNIQUE (secret)
|
||||
|
||||
);
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
await conn.execute("""
|
||||
await conn.execute(
|
||||
"""
|
||||
CREATE VIEW IF NOT EXISTS balance AS
|
||||
SELECT COALESCE(SUM(s), 0) AS balance FROM (
|
||||
SELECT SUM(amount) AS s
|
||||
FROM proofs
|
||||
WHERE amount > 0
|
||||
);
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
await conn.execute("""
|
||||
await conn.execute(
|
||||
"""
|
||||
CREATE VIEW IF NOT EXISTS balance_used AS
|
||||
SELECT COALESCE(SUM(s), 0) AS used FROM (
|
||||
SELECT SUM(amount) AS s
|
||||
FROM proofs_used
|
||||
WHERE amount > 0
|
||||
);
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
async def m002_add_proofs_reserved(db: Database):
|
||||
@@ -96,7 +106,8 @@ async def m005_wallet_keysets(db: Database):
|
||||
Stores mint keysets from different mints and epochs.
|
||||
"""
|
||||
async with db.connect() as conn:
|
||||
await conn.execute(f"""
|
||||
await conn.execute(
|
||||
f"""
|
||||
CREATE TABLE IF NOT EXISTS keysets (
|
||||
id TEXT,
|
||||
mint_url TEXT,
|
||||
@@ -108,7 +119,8 @@ async def m005_wallet_keysets(db: Database):
|
||||
UNIQUE (id, mint_url)
|
||||
|
||||
);
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
await conn.execute("ALTER TABLE proofs ADD COLUMN id TEXT")
|
||||
await conn.execute("ALTER TABLE proofs_used ADD COLUMN id TEXT")
|
||||
@@ -119,7 +131,8 @@ async def m006_invoices(db: Database):
|
||||
Stores Lightning invoices.
|
||||
"""
|
||||
async with db.connect() as conn:
|
||||
await conn.execute(f"""
|
||||
await conn.execute(
|
||||
f"""
|
||||
CREATE TABLE IF NOT EXISTS invoices (
|
||||
amount INTEGER NOT NULL,
|
||||
pr TEXT NOT NULL,
|
||||
@@ -132,7 +145,8 @@ async def m006_invoices(db: Database):
|
||||
UNIQUE (hash)
|
||||
|
||||
);
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
async def m007_nostr(db: Database):
|
||||
@@ -140,12 +154,14 @@ async def m007_nostr(db: Database):
|
||||
Stores timestamps of nostr operations.
|
||||
"""
|
||||
async with db.connect() as conn:
|
||||
await conn.execute("""
|
||||
await conn.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS nostr (
|
||||
type TEXT NOT NULL,
|
||||
last TIMESTAMP DEFAULT NULL
|
||||
)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
await conn.execute(
|
||||
"""
|
||||
INSERT INTO nostr
|
||||
@@ -172,14 +188,16 @@ async def m009_privatekey_and_determinstic_key_derivation(db: Database):
|
||||
await conn.execute("ALTER TABLE keysets ADD COLUMN counter INTEGER DEFAULT 0")
|
||||
await conn.execute("ALTER TABLE proofs ADD COLUMN derivation_path TEXT")
|
||||
await conn.execute("ALTER TABLE proofs_used ADD COLUMN derivation_path TEXT")
|
||||
await conn.execute("""
|
||||
await conn.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS seed (
|
||||
seed TEXT NOT NULL,
|
||||
mnemonic TEXT NOT NULL,
|
||||
|
||||
UNIQUE (seed, mnemonic)
|
||||
);
|
||||
""")
|
||||
"""
|
||||
)
|
||||
# await conn.execute("INSERT INTO secret_derivation (counter) VALUES (0)")
|
||||
|
||||
|
||||
|
||||
@@ -133,9 +133,12 @@ class WalletP2PK(SupportsPrivateKey, SupportsDb):
|
||||
return outputs
|
||||
|
||||
# if any of the proofs provided require SIG_ALL, we must provide it
|
||||
if any([
|
||||
P2PKSecret.deserialize(p.secret).sigflag == SigFlags.SIG_ALL for p in proofs
|
||||
]):
|
||||
if any(
|
||||
[
|
||||
P2PKSecret.deserialize(p.secret).sigflag == SigFlags.SIG_ALL
|
||||
for p in proofs
|
||||
]
|
||||
):
|
||||
outputs = await self.add_p2pk_witnesses_to_outputs(outputs)
|
||||
return outputs
|
||||
|
||||
@@ -181,9 +184,9 @@ class WalletP2PK(SupportsPrivateKey, SupportsDb):
|
||||
return proofs
|
||||
logger.debug("Spending conditions detected.")
|
||||
# P2PK signatures
|
||||
if all([
|
||||
Secret.deserialize(p.secret).kind == SecretKind.P2PK.value for p in proofs
|
||||
]):
|
||||
if all(
|
||||
[Secret.deserialize(p.secret).kind == SecretKind.P2PK.value for p in proofs]
|
||||
):
|
||||
logger.debug("P2PK redemption detected.")
|
||||
proofs = await self.add_p2pk_witnesses_to_proofs(proofs)
|
||||
|
||||
|
||||
@@ -1488,7 +1488,7 @@ class Wallet(LedgerAPI, WalletP2PK, WalletHTLC, WalletSecrets):
|
||||
|
||||
Args:
|
||||
proofs (List[Proof]): Which proofs to delete
|
||||
check_spendable (bool, optional): Asks the mint to check whether proofs are already spent before deleting them. Defaults to True.
|
||||
check_spendable (bool, optional): Asks the mint to check whether proofs are already spent before deleting them. Defaults to False.
|
||||
|
||||
Returns:
|
||||
List[Proof]: List of proofs that are still spendable.
|
||||
|
||||
@@ -4,7 +4,7 @@ from httpx import Response
|
||||
|
||||
from cashu.core.base import Amount, MeltQuote, Unit
|
||||
from cashu.core.settings import settings
|
||||
from cashu.lightning.blink import MINIMUM_FEE_MSAT, BlinkWallet
|
||||
from cashu.lightning.blink import MINIMUM_FEE_MSAT, BlinkWallet # type: ignore
|
||||
|
||||
settings.mint_blink_key = "123"
|
||||
blink = BlinkWallet(unit=Unit.sat)
|
||||
|
||||
@@ -28,6 +28,23 @@ def get_bolt11_and_invoice_id_from_invoice_command(output: str) -> Tuple[str, st
|
||||
return invoice, invoice_id
|
||||
|
||||
|
||||
def get_invoice_from_invoices_command(output: str) -> dict[str, str]:
|
||||
splitted = output.split("\n")
|
||||
removed_empty_and_hiphens = [
|
||||
value for value in splitted if value and not value.startswith("-----")
|
||||
]
|
||||
dict_output = {
|
||||
f"{value.split(': ')[0]}": value.split(": ")[1]
|
||||
for value in removed_empty_and_hiphens
|
||||
}
|
||||
|
||||
return dict_output
|
||||
|
||||
|
||||
async def reset_invoices(wallet: Wallet):
|
||||
await wallet.db.execute("DELETE FROM invoices")
|
||||
|
||||
|
||||
async def init_wallet():
|
||||
settings.debug = False
|
||||
wallet = await Wallet.with_db(
|
||||
@@ -158,6 +175,197 @@ def test_invoice_with_split(mint, cli_prefix):
|
||||
wallet = asyncio.run(init_wallet())
|
||||
assert wallet.proof_amounts.count(1) >= 10
|
||||
|
||||
@pytest.mark.skipif(not is_fake, reason="only on fakewallet")
|
||||
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))
|
||||
|
||||
# act
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
[*cli_prefix, "invoices", "--mint"],
|
||||
)
|
||||
|
||||
# assert
|
||||
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"
|
||||
|
||||
|
||||
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))
|
||||
|
||||
# act
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
[*cli_prefix, "invoices"],
|
||||
)
|
||||
|
||||
# assert
|
||||
print("INVOICES")
|
||||
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"] == str(invoice.paid)
|
||||
|
||||
@pytest.mark.skipif(not is_fake, reason="only on fakewallet")
|
||||
def test_invoices_with_onlypaid_option(cli_prefix):
|
||||
# arrange
|
||||
wallet1 = asyncio.run(init_wallet())
|
||||
asyncio.run(reset_invoices(wallet=wallet1))
|
||||
asyncio.run(wallet1.request_mint(64))
|
||||
|
||||
# act
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
[*cli_prefix, "invoices", "--only-paid", "--mint"],
|
||||
)
|
||||
|
||||
# assert
|
||||
print("INVOICES --only-paid --mint")
|
||||
assert result.exception is None
|
||||
assert result.exit_code == 0
|
||||
assert "No invoices found." in result.output
|
||||
|
||||
|
||||
def test_invoices_with_onlypaid_option_without_minting(cli_prefix):
|
||||
# arrange
|
||||
wallet1 = asyncio.run(init_wallet())
|
||||
asyncio.run(reset_invoices(wallet=wallet1))
|
||||
asyncio.run(wallet1.request_mint(64))
|
||||
|
||||
# act
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
[*cli_prefix, "invoices", "--only-paid"],
|
||||
)
|
||||
|
||||
# assert
|
||||
print("INVOICES --only-paid")
|
||||
assert result.exception is None
|
||||
assert result.exit_code == 0
|
||||
assert "No invoices found." in result.output
|
||||
|
||||
@pytest.mark.skipif(not is_fake, reason="only on fakewallet")
|
||||
def test_invoices_with_onlyunpaid_option(cli_prefix):
|
||||
# arrange
|
||||
wallet1 = asyncio.run(init_wallet())
|
||||
asyncio.run(reset_invoices(wallet=wallet1))
|
||||
asyncio.run(wallet1.request_mint(64))
|
||||
|
||||
# act
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
[*cli_prefix, "invoices", "--only-unpaid", "--mint"],
|
||||
)
|
||||
|
||||
# assert
|
||||
print("INVOICES --only-unpaid --mint")
|
||||
assert result.exception is None
|
||||
assert result.exit_code == 0
|
||||
assert "No invoices found." in result.output
|
||||
|
||||
|
||||
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))
|
||||
|
||||
# act
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
[*cli_prefix, "invoices", "--only-unpaid"],
|
||||
)
|
||||
|
||||
# assert
|
||||
print("INVOICES --only-unpaid")
|
||||
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"] == str(invoice.paid)
|
||||
|
||||
|
||||
def test_invoices_with_both_onlypaid_and_onlyunpaid_options(cli_prefix):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
[*cli_prefix, "invoices", "--only-paid", "--only-unpaid"],
|
||||
)
|
||||
assert result.exception is None
|
||||
print("INVOICES --only-paid --only-unpaid")
|
||||
assert result.exit_code == 0
|
||||
assert (
|
||||
"You should only choose one option: either --only-paid or --only-unpaid"
|
||||
in result.output
|
||||
)
|
||||
|
||||
@pytest.mark.skipif(not is_fake, reason="only on fakewallet")
|
||||
def test_invoices_with_pending_option(cli_prefix):
|
||||
# arrange
|
||||
wallet1 = asyncio.run(init_wallet())
|
||||
asyncio.run(reset_invoices(wallet=wallet1))
|
||||
asyncio.run(wallet1.request_mint(64))
|
||||
|
||||
# act
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
[*cli_prefix, "invoices", "--pending", "--mint"],
|
||||
)
|
||||
|
||||
# assert
|
||||
print("INVOICES --pending --mint")
|
||||
assert result.exception is None
|
||||
assert result.exit_code == 0
|
||||
assert "No invoices found." in result.output
|
||||
|
||||
|
||||
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))
|
||||
|
||||
# act
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
[*cli_prefix, "invoices", "--pending"],
|
||||
)
|
||||
|
||||
# assert
|
||||
print("INVOICES --pending")
|
||||
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"] == str(invoice.paid)
|
||||
|
||||
|
||||
def test_wallets(cli_prefix):
|
||||
runner = CliRunner()
|
||||
|
||||
@@ -231,9 +231,9 @@ async def test_p2pk_locktime_with_second_refund_pubkey(
|
||||
secret_lock = await wallet1.create_p2pk_lock(
|
||||
garbage_pubkey.serialize().hex(), # create lock to unspendable pubkey
|
||||
locktime_seconds=2, # locktime
|
||||
tags=Tags([
|
||||
["refund", pubkey_wallet2, pubkey_wallet1]
|
||||
]), # multiple refund pubkeys
|
||||
tags=Tags(
|
||||
[["refund", pubkey_wallet2, pubkey_wallet1]]
|
||||
), # multiple refund pubkeys
|
||||
) # sender side
|
||||
_, send_proofs = await wallet1.split_to_send(
|
||||
wallet1.proofs, 8, secret_lock=secret_lock
|
||||
@@ -388,9 +388,9 @@ async def test_p2pk_multisig_with_wrong_first_private_key(
|
||||
|
||||
|
||||
def test_tags():
|
||||
tags = Tags([
|
||||
["key1", "value1"], ["key2", "value2", "value2_1"], ["key2", "value3"]
|
||||
])
|
||||
tags = Tags(
|
||||
[["key1", "value1"], ["key2", "value2", "value2_1"], ["key2", "value3"]]
|
||||
)
|
||||
assert tags.get_tag("key1") == "value1"
|
||||
assert tags["key1"] == "value1"
|
||||
assert tags.get_tag("key2") == "value2"
|
||||
|
||||
Reference in New Issue
Block a user