diff --git a/.gitignore b/.gitignore index 3b0b00ba..5feb2737 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,4 @@ docker # Nix *result* -# Ignore extensions (post installable extension PR) -extensions/ upgrades/ \ No newline at end of file diff --git a/lnbits/extensions/cashu/static/js/dhke.js b/lnbits/extensions/cashu/static/js/dhke.js index 41c2fb46..cebef240 100644 --- a/lnbits/extensions/cashu/static/js/dhke.js +++ b/lnbits/extensions/cashu/static/js/dhke.js @@ -1,17 +1,11 @@ async function hashToCurve(secretMessage) { - console.log( - '### secretMessage', - nobleSecp256k1.utils.bytesToHex(secretMessage) - ) let point while (!point) { const hash = await nobleSecp256k1.utils.sha256(secretMessage) const hashHex = nobleSecp256k1.utils.bytesToHex(hash) const pointX = '02' + hashHex - console.log('### pointX', pointX) try { point = nobleSecp256k1.Point.fromHex(pointX) - console.log('### point', point.toHex()) } catch (error) { secretMessage = await nobleSecp256k1.utils.sha256(secretMessage) } @@ -20,19 +14,17 @@ async function hashToCurve(secretMessage) { } async function step1Alice(secretMessage) { - // todo: document & validate `secretMessage` format secretMessage = uint8ToBase64.encode(secretMessage) secretMessage = new TextEncoder().encode(secretMessage) const Y = await hashToCurve(secretMessage) - const rpk = nobleSecp256k1.utils.randomPrivateKey() - const r = bytesToNumber(rpk) + const r_bytes = nobleSecp256k1.utils.randomPrivateKey() + const r = bytesToNumber(r_bytes) const P = nobleSecp256k1.Point.fromPrivateKey(r) const B_ = Y.add(P) - return {B_: B_.toHex(true), r: nobleSecp256k1.utils.bytesToHex(rpk)} + return {B_: B_.toHex(true), r: nobleSecp256k1.utils.bytesToHex(r_bytes)} } function step3Alice(C_, r, A) { - // const rInt = BigInt(r) const rInt = bytesToNumber(r) const C = C_.subtract(A.multiply(rInt)) return C diff --git a/lnbits/extensions/cashu/templates/cashu/wallet.html b/lnbits/extensions/cashu/templates/cashu/wallet.html index 1bf6241f..e082da8b 100644 --- a/lnbits/extensions/cashu/templates/cashu/wallet.html +++ b/lnbits/extensions/cashu/templates/cashu/wallet.html @@ -1690,8 +1690,6 @@ page_container %} outputs } - console.log('payload', JSON.stringify(payload)) - const {data} = await LNbits.api.request( 'POST', `/cashu/api/v1/${this.mintId}/split`, @@ -1885,7 +1883,7 @@ page_container %} const payload = { proofs: scndProofs.flat(), amount, - invoice: this.payInvoiceData.data.request + pr: this.payInvoiceData.data.request } console.log('#### payload', JSON.stringify(payload)) try { @@ -1959,8 +1957,13 @@ page_container %} checks with the mint whether an array of proofs is still spendable or already invalidated */ + if (proofs.length == 0) { + return + } const payload = { - proofs: proofs.flat() + proofs: proofs.map(p => { + return {secret: p.secret} + }) } console.log('#### payload', JSON.stringify(payload)) try { @@ -1972,7 +1975,7 @@ page_container %} ) // delete proofs from database if it is spent - let spentProofs = proofs.filter((p, pidx) => !data[pidx]) + let spentProofs = proofs.filter((p, pidx) => !data.spendable[pidx]) if (spentProofs.length) { this.deleteProofs(spentProofs) @@ -1990,7 +1993,7 @@ page_container %} } } - return data + return data.spendable } catch (error) { console.error(error) LNbits.utils.notifyApiError(error) @@ -2033,6 +2036,9 @@ page_container %} JSON.stringify(data) ) }, + + ////////////// UI HELPERS ////////////// + setInvoicePaid: async function (payment_hash) { const invoice = this.invoicesCashu.find(i => i.hash === payment_hash) invoice.status = 'paid' @@ -2077,15 +2083,11 @@ page_container %} */ const tokenJson = atob(token) const proofs = JSON.parse(tokenJson) - let data = await this.checkProofsSpendable(proofs) - - // iterate through response of form {0: true, 1: false, ...} + const spendable = await this.checkProofsSpendable(proofs) let paid = false - for (const [key, spendable] of Object.entries(data)) { - if (!spendable) { - this.setTokenPaid(token) - paid = true - } + if (spendable.includes(true)) { + this.setTokenPaid(token) + paid = true } if (paid) { console.log('### token paid') @@ -2126,6 +2128,7 @@ page_container %} }, findTokenForAmount: function (amount) { + // unused coin selection for (const token of this.proofs) { const index = token.promises?.findIndex(p => p.amount === amount) if (index >= 0) { diff --git a/lnbits/extensions/cashu/views_api.py b/lnbits/extensions/cashu/views_api.py index dfd20cef..69e3d26a 100644 --- a/lnbits/extensions/cashu/views_api.py +++ b/lnbits/extensions/cashu/views_api.py @@ -4,18 +4,18 @@ from typing import Dict, List, Union # -------- cashu imports from cashu.core.base import ( - BlindedSignature, CheckFeesRequest, CheckFeesResponse, - CheckRequest, + CheckSpendableRequest, + CheckSpendableResponse, GetMeltResponse, GetMintResponse, Invoice, - MeltRequest, + PostMeltRequest, PostMintRequest, PostMintResponse, + PostSplitRequest, PostSplitResponse, - SplitRequest, ) from fastapi import Depends, Query from loguru import logger @@ -279,7 +279,7 @@ async def mint( @cashu_ext.post("/api/v1/{cashu_id}/melt") async def melt_coins( - payload: MeltRequest, cashu_id: str = Query(None) + payload: PostMeltRequest, cashu_id: str = Query(None) ) -> GetMeltResponse: """Invalidates proofs and pays a Lightning invoice.""" cashu: Union[None, Cashu] = await get_cashu(cashu_id) @@ -288,7 +288,7 @@ async def melt_coins( status_code=HTTPStatus.NOT_FOUND, detail="Mint does not exist." ) proofs = payload.proofs - invoice = payload.invoice + invoice = payload.pr # !!!!!!! MAKE SURE THAT PROOFS ARE ONLY FROM THIS CASHU KEYSET ID # THIS IS NECESSARY BECAUSE THE CASHU BACKEND WILL ACCEPT ANY VALID @@ -358,7 +358,7 @@ async def melt_coins( @cashu_ext.post("/api/v1/{cashu_id}/check") async def check_spendable( - payload: CheckRequest, cashu_id: str = Query(None) + payload: CheckSpendableRequest, cashu_id: str = Query(None) ) -> Dict[int, bool]: """Check whether a secret has been spent already or not.""" cashu: Union[None, Cashu] = await get_cashu(cashu_id) @@ -366,7 +366,8 @@ async def check_spendable( raise HTTPException( status_code=HTTPStatus.NOT_FOUND, detail="Mint does not exist." ) - return await ledger.check_spendable(payload.proofs) + spendableList = await ledger.check_spendable(payload.proofs) + return CheckSpendableResponse(spendable=spendableList) @cashu_ext.post("/api/v1/{cashu_id}/checkfees") @@ -395,7 +396,7 @@ async def check_fees( @cashu_ext.post("/api/v1/{cashu_id}/split") async def split( - payload: SplitRequest, cashu_id: str = Query(None) + payload: PostSplitRequest, cashu_id: str = Query(None) ) -> PostSplitResponse: """ Requetst a set of tokens with amount "total" to be split into two diff --git a/poetry.lock b/poetry.lock index f5082471..86641515 100644 --- a/poetry.lock +++ b/poetry.lock @@ -195,14 +195,14 @@ websockets = ">=10" [[package]] name = "cashu" -version = "0.8.2" +version = "0.9.0" description = "Ecash wallet and mint for Bitcoin Lightning" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "cashu-0.8.2-py3-none-any.whl", hash = "sha256:53893911763c424255bc7112aaba356e0a265e850d770338c70b2d282f67bf99"}, - {file = "cashu-0.8.2.tar.gz", hash = "sha256:4cdd34a50d14960d2dcc6f5b6120f462688090dd084387860f7a59d16aa102ff"}, + {file = "cashu-0.9.0-py3-none-any.whl", hash = "sha256:73dde901c8ea75d223f0cb37ea214028c17b798f9189b88968884c4a9c2e32a8"}, + {file = "cashu-0.9.0.tar.gz", hash = "sha256:5d5087b3b80ecd8350ea2b098605581a746fc377c0bf9f1e3a97fa5c6d06d9f2"}, ] [package.dependencies] @@ -2112,4 +2112,4 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools" [metadata] lock-version = "2.0" python-versions = "^3.10 | ^3.9 | ^3.8 | ^3.7" -content-hash = "bbbe4d958160a1e5c596c09af3c402964a7e68d9da1491e787649cee278c5eac" +content-hash = "e3ac1dcb6e10cc8fd7ee1ae88698ca6d2d412efe353578d9f2134adc512a523b" diff --git a/pyproject.toml b/pyproject.toml index 6368b1d3..cc30c311 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,8 +62,8 @@ protobuf = "4.21.12" Cerberus = "1.3.4" async-timeout = "4.0.2" pyln-client = "0.11.1" -cashu = "0.8.2" boltz-client = "0.1.3" +cashu = "0.9.0" [tool.poetry.dev-dependencies] diff --git a/requirements.txt b/requirements.txt index 87526aec..d9da1e6e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,7 @@ base58==2.1.1 ; python_version >= "3.7" and python_version < "4.0" bech32==1.2.0 ; python_version >= "3.7" and python_version < "4.0" bitstring==3.1.9 ; python_version >= "3.7" and python_version < "4.0" boltz-client==0.1.3 ; python_version >= "3.7" and python_version < "4.0" -cashu==0.8.2 ; python_version >= "3.7" and python_version < "4.0" +cashu==0.9.0 ; python_version >= "3.7" and python_version < "4.0" cerberus==1.3.4 ; python_version >= "3.7" and python_version < "4.0" certifi==2022.12.7 ; python_version >= "3.7" and python_version < "4.0" cffi==1.15.1 ; python_version >= "3.7" and python_version < "4.0"