diff --git a/.env.example b/.env.example index 78504b0..2b58494 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,7 @@ CASHU_DIR=~/.cashu # WALLET +# MINT_URL=https://localhost:3338 MINT_HOST=127.0.0.1 MINT_PORT=3338 diff --git a/cashu/core/settings.py b/cashu/core/settings.py index 5a95fbf..68a74ba 100644 --- a/cashu/core/settings.py +++ b/cashu/core/settings.py @@ -34,16 +34,18 @@ MINT_PRIVATE_KEY = env.str("MINT_PRIVATE_KEY", default=None) MINT_SERVER_HOST = env.str("MINT_SERVER_HOST", default="127.0.0.1") MINT_SERVER_PORT = env.int("MINT_SERVER_PORT", default=3338) +MINT_URL = env.str("MINT_URL", default=None) MINT_HOST = env.str("MINT_HOST", default="8333.space") MINT_PORT = env.int("MINT_PORT", default=3338) -if MINT_HOST in ["localhost", "127.0.0.1"]: - MINT_URL = f"http://{MINT_HOST}:{MINT_PORT}" -else: - MINT_URL = f"https://{MINT_HOST}:{MINT_PORT}" +if not MINT_URL: + if MINT_HOST in ["localhost", "127.0.0.1"]: + MINT_URL = f"http://{MINT_HOST}:{MINT_PORT}" + else: + MINT_URL = f"https://{MINT_HOST}:{MINT_PORT}" LNBITS_ENDPOINT = env.str("LNBITS_ENDPOINT", default=None) LNBITS_KEY = env.str("LNBITS_KEY", default=None) MAX_ORDER = 64 -VERSION = "0.2.5" +VERSION = "0.2.6" diff --git a/cashu/mint/ledger.py b/cashu/mint/ledger.py index d194863..1779743 100644 --- a/cashu/mint/ledger.py +++ b/cashu/mint/ledger.py @@ -189,11 +189,16 @@ class Ledger: ) return payment_request, checking_id - async def _check_lightning_invoice(self, payment_hash: str): + async def _check_lightning_invoice(self, amounts, payment_hash: str): """Checks with the Lightning backend whether an invoice with this payment_hash was paid.""" invoice: Invoice = await get_lightning_invoice(payment_hash, db=self.db) if invoice.issued: raise Exception("tokens already issued for this invoice.") + total_requested = sum([amount for amount in amounts]) + if total_requested > invoice.amount: + raise Exception( + f"Requested amount too high: {total_requested}. Invoice amount: {invoice.amount}" + ) status = await WALLET.get_invoice_status(payment_hash) if status.paid: await update_lightning_invoice(payment_hash, issued=True, db=self.db) @@ -242,9 +247,9 @@ class Ledger: # check if lightning invoice was paid if LIGHTNING: try: - paid = await self._check_lightning_invoice(payment_hash) - except: - raise Exception("could not check invoice.") + paid = await self._check_lightning_invoice(amounts, payment_hash) + except Exception as e: + raise Exception("could not check invoice: " + str(e)) if not paid: raise Exception("Lightning invoice not paid yet.") diff --git a/cashu/mint/router.py b/cashu/mint/router.py index 43b7c5b..1ea848a 100644 --- a/cashu/mint/router.py +++ b/cashu/mint/router.py @@ -41,7 +41,11 @@ async def request_mint(amount: int = 0): @router.post("/mint") -async def mint(payloads: MintRequest, payment_hash: Union[str, None] = None): +async def mint( + payloads: MintRequest, + bolt11: Union[str, None] = None, + payment_hash: Union[str, None] = None, +): """ Requests the minting of tokens belonging to a paid payment request. diff --git a/cashu/wallet/cli.py b/cashu/wallet/cli.py index b2fb2d4..b45ee31 100755 --- a/cashu/wallet/cli.py +++ b/cashu/wallet/cli.py @@ -104,12 +104,13 @@ async def mint(ctx, amount: int, hash: str): time.sleep(3) try: await wallet.mint(amount, r["hash"]) + paid = True + print(" Invoice paid.") except Exception as e: + # TODO: user error codes! if str(e) == "Error: Lightning invoice not paid yet.": print(".", end="", flush=True) continue - paid = True - print(" Invoice paid.") elif amount and hash: await wallet.mint(amount, hash) wallet.status() diff --git a/cashu/wallet/wallet.py b/cashu/wallet/wallet.py index 0d1e2a5..6f0cf91 100644 --- a/cashu/wallet/wallet.py +++ b/cashu/wallet/wallet.py @@ -49,6 +49,7 @@ class LedgerAPI: def __init__(self, url): self.url = url +<<<<<<< HEAD def _get_keys(self, url): resp = requests.get(url + "/keys").json() keyset_id = resp["id"] @@ -68,6 +69,17 @@ class LedgerAPI: ) print(resp) return Keyset(id=keyset_id, keys=keyset_keys, mint_url=self.url) +======= + @staticmethod + def _get_keys(url): + resp = requests.get(url + "/keys") + resp.raise_for_status() + data = resp.json() + return { + int(amt): PublicKey(bytes.fromhex(val), raw=True) + for amt, val in data.items() + } +>>>>>>> main @staticmethod def _get_output_split(amount): @@ -116,6 +128,7 @@ class LedgerAPI: def request_mint(self, amount): """Requests a mint from the server and returns Lightning invoice.""" r = requests.get(self.url + "/mint", params={"amount": amount}) + r.raise_for_status() return r.json() @staticmethod @@ -158,13 +171,11 @@ class LedgerAPI: json=payloads.dict(), params={"payment_hash": payment_hash}, ) + resp.raise_for_status() try: promises_list = resp.json() except: - if resp.status_code >= 300: - raise Exception(f"Error: {f'mint returned {resp.status_code}'}") - else: - raise Exception("Unkown mint error.") + raise Exception("Unkown mint error.") if "error" in promises_list: raise Exception("Error: {}".format(promises_list["error"])) @@ -208,14 +219,11 @@ class LedgerAPI: self.url + "/split", json=split_payload.dict(), ) - + resp.raise_for_status() try: promises_dict = resp.json() except: - if resp.status_code >= 300: - raise Exception(f"Error: {f'mint returned {resp.status_code}'}") - else: - raise Exception("Unkown mint error.") + raise Exception("Unkown mint error.") if "error" in promises_dict: raise Exception("Mint Error: {}".format(promises_dict["error"])) promises_fst = [BlindedSignature.from_dict(p) for p in promises_dict["fst"]] @@ -232,28 +240,36 @@ class LedgerAPI: async def check_spendable(self, proofs: List[Proof]): payload = CheckRequest(proofs=proofs) - return_dict = requests.post( + resp = requests.post( self.url + "/check", json=payload.dict(), - ).json() + ) + resp.raise_for_status() + return_dict = resp.json() return return_dict async def check_fees(self, payment_request: str): """Checks whether the Lightning payment is internal.""" payload = CheckFeesRequest(pr=payment_request) - return_dict = requests.post( + resp = requests.post( self.url + "/checkfees", json=payload.dict(), - ).json() + ) + resp.raise_for_status() + + return_dict = resp.json() return return_dict async def pay_lightning(self, proofs: List[Proof], invoice: str): payload = MeltRequest(proofs=proofs, invoice=invoice) - return_dict = requests.post( + resp = requests.post( self.url + "/melt", json=payload.dict(), - ).json() + ) + resp.raise_for_status() + + return_dict = resp.json() return return_dict diff --git a/pyproject.toml b/pyproject.toml index e20d5f0..62eb8f5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "cashu" -version = "0.2.5" +version = "0.2.6" description = "Ecash wallet and mint." authors = ["calle "] license = "MIT" diff --git a/setup.py b/setup.py index 27918cc..2cc3078 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ entry_points = {"console_scripts": ["cashu = cashu.wallet.cli:cli"]} setuptools.setup( name="cashu", - version="0.2.5", + version="0.2.6", description="Ecash wallet and mint with Bitcoin Lightning support", long_description=long_description, long_description_content_type="text/markdown",