diff --git a/cashu b/cashu deleted file mode 100755 index 69e131c..0000000 --- a/cashu +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env python - -import asyncio -import base64 -import json -from functools import wraps - -import click -from bech32 import bech32_decode, bech32_encode, convertbits - -from wallet.migrations import m001_initial -from wallet.wallet import Wallet as Wallet -from core.settings import MINT_URL - -# https://github.com/pallets/click/issues/85#issuecomment-503464628 -def coro(f): - @wraps(f) - def wrapper(*args, **kwargs): - return asyncio.run(f(*args, **kwargs)) - - return wrapper - - -@click.command("mint") -@click.option("--host", default=MINT_URL, help="Mint hostname.") -@click.option("--wallet", default="wallet", help="Wallet to use.") -@click.option("--mint", default=0, help="Mint tokens.") -@click.option("--hash", default="", help="Hash of the paid invoice.") -@click.option("--send", default=0, help="Send tokens.") -@click.option("--receive", default="", help="Receive tokens.") -@click.option("--invalidate", default="", help="Invalidate tokens.") -@coro -async def main(host, wallet, mint, hash, send, receive, invalidate): - wallet = Wallet(host, f"data/{wallet}", wallet) - await m001_initial(db=wallet.db) - await wallet.load_proofs() - if mint and not hash: - print(f"Balance: {wallet.balance}") - r = await wallet.request_mint(mint) - print(r) - - if mint and hash: - print(f"Balance: {wallet.balance}") - await wallet.mint(mint, hash) - print(f"Balance: {wallet.balance}") - - if send: - wallet.status() - _, send_proofs = await wallet.split(wallet.proofs, send) - print(base64.urlsafe_b64encode(json.dumps(send_proofs).encode()).decode()) - - if receive: - wallet.status() - proofs = json.loads(base64.urlsafe_b64decode(receive)) - _, _ = await wallet.redeem(proofs) - wallet.status() - - if invalidate: - wallet.status() - proofs = json.loads(base64.urlsafe_b64decode(invalidate)) - await wallet.invalidate(proofs) - wallet.status() - - -if __name__ == "__main__": - main() - - -@click.command("send") -@click.option("--send", default=1, help="Mint tokens.") -@coro -async def send(send): - print("asd") - # w1_fst_proofs, w1_snd_proofs = await wallet.split(proofs, 20) - return "asd" diff --git a/cashu.py b/cashu.py new file mode 100755 index 0000000..91328f5 --- /dev/null +++ b/cashu.py @@ -0,0 +1 @@ +# for mysterious reasons, this file needs to exist for `poetry run cashu` to work diff --git a/mint/app.py b/mint/app.py index da0189d..d290751 100644 --- a/mint/app.py +++ b/mint/app.py @@ -3,13 +3,15 @@ import logging import sys from typing import Union +import click +import uvicorn from ecc.curve import Point, secp256k1 from fastapi import FastAPI from loguru import logger import core.settings as settings from core.base import MintPayloads, SplitPayload -from core.settings import MINT_PRIVATE_KEY +from core.settings import MINT_PRIVATE_KEY, MINT_SERVER_HOST, MINT_SERVER_PORT from lightning import WALLET from mint.ledger import Ledger from mint.migrations import m001_initial @@ -148,5 +150,50 @@ async def split(payload: SplitPayload): return {"error": str(exc)} -# if __name__ == "__main__": -# uvicorn.run(app, host="127.0.0.1", port=5049) +@click.command( + context_settings=dict( + ignore_unknown_options=True, + allow_extra_args=True, + ) +) +@click.option("--port", default=MINT_SERVER_PORT, help="Port to listen on") +@click.option("--host", default=MINT_SERVER_HOST, help="Host to run mint on") +@click.option("--ssl-keyfile", default=None, help="Path to SSL keyfile") +@click.option("--ssl-certfile", default=None, help="Path to SSL certificate") +@click.pass_context +def main( + ctx, + port: int = MINT_SERVER_PORT, + host: str = MINT_SERVER_HOST, + ssl_keyfile: str = None, + ssl_certfile: str = None, +): + """Launched with `poetry run mint` at root level""" + # this beautiful beast parses all command line arguments and passes them to the uvicorn server + d = dict() + for a in ctx.args: + item = a.split("=") + if len(item) > 1: # argument like --key=value + print(a, item) + d[item[0].strip("--").replace("-", "_")] = ( + int(item[1]) # need to convert to int if it's a number + if item[1].isdigit() + else item[1] + ) + else: + d[a.strip("--")] = True # argument like --key + + config = uvicorn.Config( + "mint.app:app", + port=port, + host=host, + ssl_keyfile=ssl_keyfile, + ssl_certfile=ssl_certfile, + **d, + ) + server = uvicorn.Server(config) + server.run() + + +if __name__ == "__main__": + main() diff --git a/mint/ledger.py b/mint/ledger.py index f4027c7..36fa5a1 100644 --- a/mint/ledger.py +++ b/mint/ledger.py @@ -13,14 +13,9 @@ from core.db import Database from core.settings import MAX_ORDER from core.split import amount_split from lightning import WALLET -from mint.crud import ( - get_lightning_invoice, - get_proofs_used, - invalidate_proof, - store_lightning_invoice, - store_promise, - update_lightning_invoice, -) +from mint.crud import (get_lightning_invoice, get_proofs_used, + invalidate_proof, store_lightning_invoice, + store_promise, update_lightning_invoice) class Ledger: diff --git a/pyproject.toml b/pyproject.toml index 0ab6164..fab6fd1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,3 +39,7 @@ isort = "^5.10.1" [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" + +[tool.poetry.scripts] +mint = "mint.app:main" +cashu = "wallet.cashu:cli" \ No newline at end of file diff --git a/wallet/wallet.py b/wallet/wallet.py index 311abdb..c31cd6c 100644 --- a/wallet/wallet.py +++ b/wallet/wallet.py @@ -139,6 +139,7 @@ class Wallet(LedgerAPI): return await self.split(proofs, sum(p["amount"] for p in proofs)) async def split(self, proofs, amount): + assert len(proofs) > 0, ValueError("no proofs provided.") fst_proofs, snd_proofs = super().split(proofs, amount) if len(fst_proofs) == 0 and len(snd_proofs) == 0: raise Exception("received no splits")