From b41bd694a1d983dd00f52c0206573370b1f5f90f Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Thu, 13 Oct 2022 22:10:33 +0200 Subject: [PATCH] endpoints work --- lnbits/extensions/cashu/crud.py | 20 +- lnbits/extensions/cashu/migrations.py | 3 +- lnbits/extensions/cashu/models.py | 4 +- lnbits/extensions/cashu/views_api.py | 675 +++++++++++++------------- poetry.lock | 15 + pyproject.toml | 1 + 6 files changed, 371 insertions(+), 347 deletions(-) diff --git a/lnbits/extensions/cashu/crud.py b/lnbits/extensions/cashu/crud.py index 31c185dc..a56eadf0 100644 --- a/lnbits/extensions/cashu/crud.py +++ b/lnbits/extensions/cashu/crud.py @@ -59,21 +59,14 @@ from lnbits.db import Database, Connection # return await update_lightning_invoice(*args, **kwags) -async def create_cashu(wallet_id: str, data: Cashu) -> Cashu: - cashu_id = urlsafe_short_hash() - - entropy = bytes([random.getrandbits(8) for i in range(16)]) - mnemonic = bip39.mnemonic_from_bytes(entropy) - seed = bip39.mnemonic_to_seed(mnemonic) - root = bip32.HDKey.from_seed(seed, version=NETWORKS["main"]["xprv"]) - - bip44_xprv = root.derive("m/44h/1h/0h") - bip44_xpub = bip44_xprv.to_public() +async def create_cashu( + cashu_id: str, keyset_id: str, wallet_id: str, data: Cashu +) -> Cashu: await db.execute( """ - INSERT INTO cashu.cashu (id, wallet, name, tickershort, fraction, maxsats, coins, prvkey, pubkey) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) + INSERT INTO cashu.cashu (id, wallet, name, tickershort, fraction, maxsats, coins, keyset_id) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) """, ( cashu_id, @@ -83,8 +76,7 @@ async def create_cashu(wallet_id: str, data: Cashu) -> Cashu: data.fraction, data.maxsats, data.coins, - bip44_xprv.to_base58(), - bip44_xpub.to_base58(), + keyset_id, ), ) diff --git a/lnbits/extensions/cashu/migrations.py b/lnbits/extensions/cashu/migrations.py index 6af53d5d..3f799534 100644 --- a/lnbits/extensions/cashu/migrations.py +++ b/lnbits/extensions/cashu/migrations.py @@ -12,8 +12,7 @@ async def m001_initial(db): fraction BOOL, maxsats INT, coins INT, - prvkey TEXT NOT NULL, - pubkey TEXT NOT NULL + keyset_id TEXT NOT NULL ); """ ) diff --git a/lnbits/extensions/cashu/models.py b/lnbits/extensions/cashu/models.py index 596db047..49fa9059 100644 --- a/lnbits/extensions/cashu/models.py +++ b/lnbits/extensions/cashu/models.py @@ -17,7 +17,7 @@ class Cashu(BaseModel): pubkey: str = Query(None) @classmethod - def from_row(cls, row: Row) -> "TPoS": + def from_row(cls, row: Row): return cls(**dict(row)) @@ -28,7 +28,7 @@ class Pegs(BaseModel): amount: str @classmethod - def from_row(cls, row: Row) -> "TPoS": + def from_row(cls, row: Row): return cls(**dict(row)) diff --git a/lnbits/extensions/cashu/views_api.py b/lnbits/extensions/cashu/views_api.py index e643c2ac..f47f8744 100644 --- a/lnbits/extensions/cashu/views_api.py +++ b/lnbits/extensions/cashu/views_api.py @@ -15,6 +15,7 @@ from lnbits.core.services import check_transaction_status, create_invoice from lnbits.core.views.api import api_payment from lnbits.decorators import WalletTypeInfo, get_key_type, require_admin_key from lnbits.wallets.base import PaymentStatus +from lnbits.helpers import urlsafe_short_hash from . import cashu_ext from .core.base import CashuError, PostSplitResponse, SplitRequest @@ -29,13 +30,6 @@ from .crud import ( update_lightning_invoice, ) -# from cashu.mint.crud import ( -# get_lightning_invoice, -# store_lightning_invoice, -# store_promise, -# update_lightning_invoice, -# ) - # from .ledger import mint, request_mint from .mint import generate_promises, get_pubkeys, melt, split from .models import ( @@ -49,327 +43,8 @@ from .models import ( SplitPayload, ) -######################################## -#################MINT CRUD############## -######################################## - -# todo: use /mints -@cashu_ext.get("/api/v1/cashus", status_code=HTTPStatus.OK) -async def api_cashus( - all_wallets: bool = Query(False), wallet: WalletTypeInfo = Depends(get_key_type) -): - wallet_ids = [wallet.wallet.id] - if all_wallets: - wallet_ids = (await get_user(wallet.wallet.user)).wallet_ids - - return [cashu.dict() for cashu in await get_cashus(wallet_ids)] - - -@cashu_ext.post("/api/v1/cashus", status_code=HTTPStatus.CREATED) -async def api_cashu_create(data: Cashu, wallet: WalletTypeInfo = Depends(get_key_type)): - cashu = await create_cashu(wallet_id=wallet.wallet.id, data=data) - logger.debug(cashu) - return cashu.dict() - - -@cashu_ext.post("/api/v1/cashus/upodatekeys", status_code=HTTPStatus.CREATED) -async def api_cashu_update_keys( - data: Cashu, wallet: WalletTypeInfo = Depends(get_key_type) -): - cashu = await get_cashu(data.id) - - cashu = await create_cashu(wallet_id=wallet.wallet.id, data=data) - logger.debug(cashu) - return cashu.dict() - - -@cashu_ext.delete("/api/v1/cashus/{cashu_id}") -async def api_cashu_delete( - cashu_id: str, wallet: WalletTypeInfo = Depends(require_admin_key) -): - cashu = await get_cashu(cashu_id) - - if not cashu: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="Cashu does not exist." - ) - - if cashu.wallet != wallet.wallet.id: - raise HTTPException(status_code=HTTPStatus.FORBIDDEN, detail="Not your Cashu.") - - await delete_cashu(cashu_id) - raise HTTPException(status_code=HTTPStatus.NO_CONTENT) - - -######################################## -#################????################### -######################################## -@cashu_ext.post("/api/v1/cashus/{cashu_id}/invoices", status_code=HTTPStatus.CREATED) -async def api_cashu_create_invoice( - amount: int = Query(..., ge=1), tipAmount: int = None, cashu_id: str = None -): - cashu = await get_cashu(cashu_id) - - if not cashu: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="TPoS does not exist." - ) - - if tipAmount: - amount += tipAmount - - try: - payment_hash, payment_request = await create_invoice( - wallet_id=cashu.wallet, - amount=amount, - memo=f"{cashu.name}", - extra={"tag": "cashu", "tipAmount": tipAmount, "cashuId": cashu_id}, - ) - except Exception as e: - raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e)) - - return {"payment_hash": payment_hash, "payment_request": payment_request} - - -@cashu_ext.post( - "/api/v1/cashus/{cashu_id}/invoices/{payment_request}/pay", - status_code=HTTPStatus.OK, -) -async def api_cashu_pay_invoice( - lnurl_data: PayLnurlWData, payment_request: str = None, cashu_id: str = None -): - cashu = await get_cashu(cashu_id) - - if not cashu: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="TPoS does not exist." - ) - - lnurl = ( - lnurl_data.lnurl.replace("lnurlw://", "") - .replace("lightning://", "") - .replace("LIGHTNING://", "") - .replace("lightning:", "") - .replace("LIGHTNING:", "") - ) - - if lnurl.lower().startswith("lnurl"): - lnurl = decode_lnurl(lnurl) - else: - lnurl = "https://" + lnurl - - async with httpx.AsyncClient() as client: - try: - r = await client.get(lnurl, follow_redirects=True) - if r.is_error: - lnurl_response = {"success": False, "detail": "Error loading"} - else: - resp = r.json() - if resp["tag"] != "withdrawRequest": - lnurl_response = {"success": False, "detail": "Wrong tag type"} - else: - r2 = await client.get( - resp["callback"], - follow_redirects=True, - params={ - "k1": resp["k1"], - "pr": payment_request, - }, - ) - resp2 = r2.json() - if r2.is_error: - lnurl_response = { - "success": False, - "detail": "Error loading callback", - } - elif resp2["status"] == "ERROR": - lnurl_response = {"success": False, "detail": resp2["reason"]} - else: - lnurl_response = {"success": True, "detail": resp2} - except (httpx.ConnectError, httpx.RequestError): - lnurl_response = {"success": False, "detail": "Unexpected error occurred"} - - return lnurl_response - - -@cashu_ext.get( - "/api/v1/cashus/{cashu_id}/invoices/{payment_hash}", status_code=HTTPStatus.OK -) -async def api_cashu_check_invoice(cashu_id: str, payment_hash: str): - cashu = await get_cashu(cashu_id) - if not cashu: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="TPoS does not exist." - ) - try: - status = await api_payment(payment_hash) - - except Exception as exc: - logger.error(exc) - return {"paid": False} - return status - - -######################################## -#################MINT################### -######################################## - - -# @cashu_ext.get("/api/v1/cashu/{cashu_id}/keys", status_code=HTTPStatus.OK) -# async def keys(cashu_id: str = Query(False)): -# """Get the public keys of the mint""" -# mint = await get_cashu(cashu_id) -# if mint is None: -# raise HTTPException( -# status_code=HTTPStatus.NOT_FOUND, detail="Mint does not exist." -# ) -# return get_pubkeys(mint.prvkey) - - -@cashu_ext.get("/api/v1/cashu/{cashu_id}/mint") -async def mint_pay_request(amount: int = 0, cashu_id: str = Query(None)): - """Request minting of tokens. Server responds with a Lightning invoice.""" - - cashu = await get_cashu(cashu_id) - if cashu is None: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="Mint does not exist." - ) - - try: - payment_hash, payment_request = await create_invoice( - wallet_id=cashu.wallet, - amount=amount, - memo=f"{cashu.name}", - extra={"tag": "cashu"}, - ) - invoice = Invoice( - amount=amount, pr=payment_request, hash=payment_hash, issued=False - ) - await store_lightning_invoice(cashu_id, invoice) - except Exception as e: - logger.error(e) - raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e)) - - return {"pr": payment_request, "hash": payment_hash} - - -@cashu_ext.post("/api/v1/cashu/{cashu_id}/mint") -async def mint_coins( - data: MintPayloads, - cashu_id: str = Query(None), - payment_hash: Union[str, None] = None, -): - """ - Requests the minting of tokens belonging to a paid payment request. - Call this endpoint after `GET /mint`. - """ - cashu: Cashu = await get_cashu(cashu_id) - if cashu is None: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="Mint does not exist." - ) - invoice: Invoice = ( - None - if payment_hash == None - else await get_lightning_invoice(cashu_id, payment_hash) - ) - if invoice is None: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="Mint does not have this invoice." - ) - if invoice.issued == True: - raise HTTPException( - status_code=HTTPStatus.PAYMENT_REQUIRED, - detail="Tokens already issued for this invoice.", - ) - - total_requested = sum([bm.amount for bm in data.blinded_messages]) - if total_requested > invoice.amount: - raise HTTPException( - status_code=HTTPStatus.PAYMENT_REQUIRED, - detail=f"Requested amount too high: {total_requested}. Invoice amount: {invoice.amount}", - ) - - status: PaymentStatus = await check_transaction_status(cashu.wallet, payment_hash) - # todo: revert to: status.paid != True: - if status.paid != True: - raise HTTPException( - status_code=HTTPStatus.PAYMENT_REQUIRED, detail="Invoice not paid." - ) - try: - await update_lightning_invoice(cashu_id, payment_hash, True) - - amounts = [] - B_s = [] - for payload in data.blinded_messages: - amounts.append(payload.amount) - B_s.append(PublicKey(bytes.fromhex(payload.B_), raw=True)) - - promises = await generate_promises(cashu.prvkey, amounts, B_s) - for amount, B_, p in zip(amounts, B_s, promises): - await store_promise(amount, B_.serialize().hex(), p.C_, cashu_id) - - return promises - except Exception as e: - logger.error(e) - raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e)) - - -@cashu_ext.post("/api/v1/cashu/{cashu_id}/melt") -async def melt_coins(payload: MeltPayload, cashu_id: str = Query(None)): - """Invalidates proofs and pays a Lightning invoice.""" - cashu: Cashu = await get_cashu(cashu_id) - if cashu is None: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="Mint does not exist." - ) - try: - ok, preimage = await melt(cashu, payload.proofs, payload.invoice) - return {"paid": ok, "preimage": preimage} - except Exception as e: - logger.error(e) - raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e)) - - -@cashu_ext.post("/api/v1/cashu/{cashu_id}/check") -async def check_spendable_coins(payload: CheckPayload, cashu_id: str = Query(None)): - return await check_spendable(payload.proofs, cashu_id) - - -@cashu_ext.post("/api/v1/cashu/{cashu_id}/split") -async def split_proofs(payload: SplitRequest, cashu_id: str = Query(None)): - """ - Requetst a set of tokens with amount "total" to be split into two - newly minted sets with amount "split" and "total-split". - """ - print("### RECEIVE") - print("payload", json.dumps(payload, default=vars)) - cashu: Cashu = await get_cashu(cashu_id) - if cashu is None: - raise HTTPException( - status_code=HTTPStatus.NOT_FOUND, detail="Mint does not exist." - ) - proofs = payload.proofs - amount = payload.amount - outputs = payload.outputs.blinded_messages if payload.outputs else None - try: - split_return = await split(cashu, proofs, amount, outputs) - except Exception as exc: - raise CashuError(error=str(exc)) - if not split_return: - return {"error": "there was a problem with the split."} - frst_promises, scnd_promises = split_return - resp = PostSplitResponse(fst=frst_promises, snd=scnd_promises) - print("### resp", json.dumps(resp, default=vars)) - return resp - - -################################################################## -################################################################## -# CASHU LIB -################################################################## +############### IMPORT CALLE from typing import Dict, List, Union from fastapi import APIRouter @@ -389,11 +64,54 @@ from cashu.core.base import ( ) from cashu.core.errors import CashuError + +######################################## +############### LNBITS MINTS ########### +######################################## + +# todo: use /mints +@cashu_ext.get("/cashus", status_code=HTTPStatus.OK) +async def api_cashus( + all_wallets: bool = Query(False), wallet: WalletTypeInfo = Depends(get_key_type) +): + wallet_ids = [wallet.wallet.id] + if all_wallets: + wallet_ids = (await get_user(wallet.wallet.user)).wallet_ids + + return [cashu.dict() for cashu in await get_cashus(wallet_ids)] + + +@cashu_ext.post("/cashus", status_code=HTTPStatus.CREATED) +async def api_cashu_create(data: Cashu, wallet: WalletTypeInfo = Depends(get_key_type)): + cashu_id = urlsafe_short_hash() + # generate a new keyset in cashu + keyset = await ledger.load_keyset(cashu_id) + + cashu = await create_cashu( + cashu_id=cashu_id, keyset_id=keyset.id, wallet_id=wallet.wallet.id, data=data + ) + logger.debug(cashu) + return cashu.dict() + + +####################################### +########### CASHU ENDPOINTS ########### +####################################### + + from . import db, ledger -@cashu_ext.get("/keys") -async def keys() -> dict[int, str]: +@cashu_ext.get("{cashu_id}/keys", status_code=HTTPStatus.OK) +async def keys(cashu_id: str = None) -> dict[int, str]: + + cashu = await get_cashu(cashu_id) + + if not cashu: + raise HTTPException( + status_code=HTTPStatus.NOT_FOUND, detail="TPoS does not exist." + ) + """Get the public keys of the mint""" return ledger.get_keyset() @@ -489,3 +207,302 @@ async def split( frst_promises, scnd_promises = split_return resp = PostSplitResponse(fst=frst_promises, snd=scnd_promises) return resp + + +# @cashu_ext.post("/api/v1/cashus/upodatekeys", status_code=HTTPStatus.CREATED) +# async def api_cashu_update_keys( +# data: Cashu, wallet: WalletTypeInfo = Depends(get_key_type) +# ): +# cashu = await get_cashu(data.id) + +# cashu = await create_cashu(wallet_id=wallet.wallet.id, data=data) +# logger.debug(cashu) +# return cashu.dict() + + +# @cashu_ext.delete("/api/v1/cashus/{cashu_id}") +# async def api_cashu_delete( +# cashu_id: str, wallet: WalletTypeInfo = Depends(require_admin_key) +# ): +# cashu = await get_cashu(cashu_id) + +# if not cashu: +# raise HTTPException( +# status_code=HTTPStatus.NOT_FOUND, detail="Cashu does not exist." +# ) + +# if cashu.wallet != wallet.wallet.id: +# raise HTTPException(status_code=HTTPStatus.FORBIDDEN, detail="Not your Cashu.") + +# await delete_cashu(cashu_id) +# raise HTTPException(status_code=HTTPStatus.NO_CONTENT) + + +# ######################################## +# #################????################### +# ######################################## +# @cashu_ext.post("/api/v1/cashus/{cashu_id}/invoices", status_code=HTTPStatus.CREATED) +# async def api_cashu_create_invoice( +# amount: int = Query(..., ge=1), tipAmount: int = None, cashu_id: str = None +# ): +# cashu = await get_cashu(cashu_id) + +# if not cashu: +# raise HTTPException( +# status_code=HTTPStatus.NOT_FOUND, detail="TPoS does not exist." +# ) + +# if tipAmount: +# amount += tipAmount + +# try: +# payment_hash, payment_request = await create_invoice( +# wallet_id=cashu.wallet, +# amount=amount, +# memo=f"{cashu.name}", +# extra={"tag": "cashu", "tipAmount": tipAmount, "cashuId": cashu_id}, +# ) +# except Exception as e: +# raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e)) + +# return {"payment_hash": payment_hash, "payment_request": payment_request} + + +# @cashu_ext.post( +# "/api/v1/cashus/{cashu_id}/invoices/{payment_request}/pay", +# status_code=HTTPStatus.OK, +# ) +# async def api_cashu_pay_invoice( +# lnurl_data: PayLnurlWData, payment_request: str = None, cashu_id: str = None +# ): +# cashu = await get_cashu(cashu_id) + +# if not cashu: +# raise HTTPException( +# status_code=HTTPStatus.NOT_FOUND, detail="TPoS does not exist." +# ) + +# lnurl = ( +# lnurl_data.lnurl.replace("lnurlw://", "") +# .replace("lightning://", "") +# .replace("LIGHTNING://", "") +# .replace("lightning:", "") +# .replace("LIGHTNING:", "") +# ) + +# if lnurl.lower().startswith("lnurl"): +# lnurl = decode_lnurl(lnurl) +# else: +# lnurl = "https://" + lnurl + +# async with httpx.AsyncClient() as client: +# try: +# r = await client.get(lnurl, follow_redirects=True) +# if r.is_error: +# lnurl_response = {"success": False, "detail": "Error loading"} +# else: +# resp = r.json() +# if resp["tag"] != "withdrawRequest": +# lnurl_response = {"success": False, "detail": "Wrong tag type"} +# else: +# r2 = await client.get( +# resp["callback"], +# follow_redirects=True, +# params={ +# "k1": resp["k1"], +# "pr": payment_request, +# }, +# ) +# resp2 = r2.json() +# if r2.is_error: +# lnurl_response = { +# "success": False, +# "detail": "Error loading callback", +# } +# elif resp2["status"] == "ERROR": +# lnurl_response = {"success": False, "detail": resp2["reason"]} +# else: +# lnurl_response = {"success": True, "detail": resp2} +# except (httpx.ConnectError, httpx.RequestError): +# lnurl_response = {"success": False, "detail": "Unexpected error occurred"} + +# return lnurl_response + + +# @cashu_ext.get( +# "/api/v1/cashus/{cashu_id}/invoices/{payment_hash}", status_code=HTTPStatus.OK +# ) +# async def api_cashu_check_invoice(cashu_id: str, payment_hash: str): +# cashu = await get_cashu(cashu_id) +# if not cashu: +# raise HTTPException( +# status_code=HTTPStatus.NOT_FOUND, detail="TPoS does not exist." +# ) +# try: +# status = await api_payment(payment_hash) + +# except Exception as exc: +# logger.error(exc) +# return {"paid": False} +# return status + + +# ######################################## +# #################MINT################### +# ######################################## + + +# # @cashu_ext.get("/api/v1/cashu/{cashu_id}/keys", status_code=HTTPStatus.OK) +# # async def keys(cashu_id: str = Query(False)): +# # """Get the public keys of the mint""" +# # mint = await get_cashu(cashu_id) +# # if mint is None: +# # raise HTTPException( +# # status_code=HTTPStatus.NOT_FOUND, detail="Mint does not exist." +# # ) +# # return get_pubkeys(mint.prvkey) + + +# @cashu_ext.get("/api/v1/cashu/{cashu_id}/mint") +# async def mint_pay_request(amount: int = 0, cashu_id: str = Query(None)): +# """Request minting of tokens. Server responds with a Lightning invoice.""" + +# cashu = await get_cashu(cashu_id) +# if cashu is None: +# raise HTTPException( +# status_code=HTTPStatus.NOT_FOUND, detail="Mint does not exist." +# ) + +# try: +# payment_hash, payment_request = await create_invoice( +# wallet_id=cashu.wallet, +# amount=amount, +# memo=f"{cashu.name}", +# extra={"tag": "cashu"}, +# ) +# invoice = Invoice( +# amount=amount, pr=payment_request, hash=payment_hash, issued=False +# ) +# await store_lightning_invoice(cashu_id, invoice) +# except Exception as e: +# logger.error(e) +# raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e)) + +# return {"pr": payment_request, "hash": payment_hash} + + +# @cashu_ext.post("/api/v1/cashu/{cashu_id}/mint") +# async def mint_coins( +# data: MintPayloads, +# cashu_id: str = Query(None), +# payment_hash: Union[str, None] = None, +# ): +# """ +# Requests the minting of tokens belonging to a paid payment request. +# Call this endpoint after `GET /mint`. +# """ +# cashu: Cashu = await get_cashu(cashu_id) +# if cashu is None: +# raise HTTPException( +# status_code=HTTPStatus.NOT_FOUND, detail="Mint does not exist." +# ) +# invoice: Invoice = ( +# None +# if payment_hash == None +# else await get_lightning_invoice(cashu_id, payment_hash) +# ) +# if invoice is None: +# raise HTTPException( +# status_code=HTTPStatus.NOT_FOUND, detail="Mint does not have this invoice." +# ) +# if invoice.issued == True: +# raise HTTPException( +# status_code=HTTPStatus.PAYMENT_REQUIRED, +# detail="Tokens already issued for this invoice.", +# ) + +# total_requested = sum([bm.amount for bm in data.blinded_messages]) +# if total_requested > invoice.amount: +# raise HTTPException( +# status_code=HTTPStatus.PAYMENT_REQUIRED, +# detail=f"Requested amount too high: {total_requested}. Invoice amount: {invoice.amount}", +# ) + +# status: PaymentStatus = await check_transaction_status(cashu.wallet, payment_hash) +# # todo: revert to: status.paid != True: +# if status.paid != True: +# raise HTTPException( +# status_code=HTTPStatus.PAYMENT_REQUIRED, detail="Invoice not paid." +# ) +# try: +# await update_lightning_invoice(cashu_id, payment_hash, True) + +# amounts = [] +# B_s = [] +# for payload in data.blinded_messages: +# amounts.append(payload.amount) +# B_s.append(PublicKey(bytes.fromhex(payload.B_), raw=True)) + +# promises = await generate_promises(cashu.prvkey, amounts, B_s) +# for amount, B_, p in zip(amounts, B_s, promises): +# await store_promise(amount, B_.serialize().hex(), p.C_, cashu_id) + +# return promises +# except Exception as e: +# logger.error(e) +# raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e)) + + +# @cashu_ext.post("/api/v1/cashu/{cashu_id}/melt") +# async def melt_coins(payload: MeltPayload, cashu_id: str = Query(None)): +# """Invalidates proofs and pays a Lightning invoice.""" +# cashu: Cashu = await get_cashu(cashu_id) +# if cashu is None: +# raise HTTPException( +# status_code=HTTPStatus.NOT_FOUND, detail="Mint does not exist." +# ) +# try: +# ok, preimage = await melt(cashu, payload.proofs, payload.invoice) +# return {"paid": ok, "preimage": preimage} +# except Exception as e: +# logger.error(e) +# raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e)) + + +# @cashu_ext.post("/api/v1/cashu/{cashu_id}/check") +# async def check_spendable_coins(payload: CheckPayload, cashu_id: str = Query(None)): +# return await check_spendable(payload.proofs, cashu_id) + + +# @cashu_ext.post("/api/v1/cashu/{cashu_id}/split") +# async def split_proofs(payload: SplitRequest, cashu_id: str = Query(None)): +# """ +# Requetst a set of tokens with amount "total" to be split into two +# newly minted sets with amount "split" and "total-split". +# """ +# print("### RECEIVE") +# print("payload", json.dumps(payload, default=vars)) +# cashu: Cashu = await get_cashu(cashu_id) +# if cashu is None: +# raise HTTPException( +# status_code=HTTPStatus.NOT_FOUND, detail="Mint does not exist." +# ) +# proofs = payload.proofs +# amount = payload.amount +# outputs = payload.outputs.blinded_messages if payload.outputs else None +# try: +# split_return = await split(cashu, proofs, amount, outputs) +# except Exception as exc: +# raise CashuError(error=str(exc)) +# if not split_return: +# return {"error": "there was a problem with the split."} +# frst_promises, scnd_promises = split_return +# resp = PostSplitResponse(fst=frst_promises, snd=scnd_promises) +# print("### resp", json.dumps(resp, default=vars)) +# return resp + + +################################################################## +################################################################## +# CASHU LIB +################################################################## diff --git a/poetry.lock b/poetry.lock index 079b2b99..57d3f6d6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -871,6 +871,17 @@ typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\"" [package.extras] full = ["itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"] +[[package]] +name = "starlette-context" +version = "0.3.4" +description = "Access context in Starlette" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +starlette = "*" + [[package]] name = "tomli" version = "2.0.1" @@ -1790,6 +1801,10 @@ starlette = [ {file = "starlette-0.19.1-py3-none-any.whl", hash = "sha256:5a60c5c2d051f3a8eb546136aa0c9399773a689595e099e0877704d5888279bf"}, {file = "starlette-0.19.1.tar.gz", hash = "sha256:c6d21096774ecb9639acad41b86b7706e52ba3bf1dc13ea4ed9ad593d47e24c7"}, ] +starlette-context = [ + {file = "starlette_context-0.3.4-py37-none-any.whl", hash = "sha256:b16bf17bd3ead7ded2f458aebf7f913744b9cf28305e16c69b435a6c6ddf1135"}, + {file = "starlette_context-0.3.4.tar.gz", hash = "sha256:2d28e1838302fb5d5adacadc10fb73fb2d5cca1f0aa1e279698701cc96f1567c"}, +] tomli = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, diff --git a/pyproject.toml b/pyproject.toml index b99bb353..d15a4fc5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,6 +63,7 @@ protobuf = "^4.21.6" Cerberus = "^1.3.4" async-timeout = "^4.0.2" pyln-client = "0.11.1" +starlette-context = "^0.3.4" [tool.poetry.dev-dependencies] isort = "^5.10.1"