Issue #313: allow checking pending invoices (#493)

* 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:
Guilherme Pereira
2024-04-03 16:51:15 +01:00
committed by GitHub
parent b8ad0e0a8f
commit 3b2f1aa6f4
9 changed files with 394 additions and 74 deletions

View File

@@ -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)

View File

@@ -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()

View File

@@ -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"