From d8be5d7b7cf4f96b5890faf436ea0a124bb2a208 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Tue, 11 Oct 2022 13:51:35 +0300 Subject: [PATCH] feat: sell fixed amount token --- lnbits/extensions/cashu/mint.py | 2 +- lnbits/extensions/cashu/mint_helper.py | 8 +- lnbits/extensions/cashu/static/js/base64.js | 73 +++++++++---------- .../cashu/templates/cashu/wallet.html | 64 ++++++++-------- 4 files changed, 72 insertions(+), 75 deletions(-) diff --git a/lnbits/extensions/cashu/mint.py b/lnbits/extensions/cashu/mint.py index 3388b45ab..883d0fa9c 100644 --- a/lnbits/extensions/cashu/mint.py +++ b/lnbits/extensions/cashu/mint.py @@ -71,7 +71,7 @@ async def melt(cashu: Cashu, proofs: List[Proof], invoice: str): fees_msat = await check_fees(cashu.wallet, invoice_obj) assert total_provided >= amount + fees_msat / 1000, Exception( - "provided proofs not enough for Lightning payment." + f"Provided proofs (${total_provided} sats) not enough for Lightning payment ({amount + fees_msat} sats)." ) await pay_invoice( diff --git a/lnbits/extensions/cashu/mint_helper.py b/lnbits/extensions/cashu/mint_helper.py index 3892c67f6..4db929463 100644 --- a/lnbits/extensions/cashu/mint_helper.py +++ b/lnbits/extensions/cashu/mint_helper.py @@ -33,19 +33,21 @@ def derive_pubkeys(keys: List[PrivateKey]): # async required? async def verify_proof(master_prvkey: str, proofs_used: Set[str], proof: Proof): """Verifies that the proof of promise was issued by this ledger.""" - # if proof.secret in proofs_used: - # raise Exception(f"tokens already spent. Secret: {proof.secret}") + if proof.secret in proofs_used: + raise Exception(f"tokens already spent. Secret: {proof.secret}") secret_key = derive_keys(master_prvkey)[ proof.amount ] # Get the correct key to check against C = PublicKey(bytes.fromhex(proof.C), raw=True) - secret = base64.urlsafe_b64decode(proof.secret) + secret = base64.standard_b64decode(proof.secret) print('### secret', secret) validMintSig = verify(secret_key, C, secret) if validMintSig != True: raise Exception(f"tokens not valid. Secret: {proof.secret}") + + def verify_split_amount(amount: int): """Split amount like output amount can't be negative or too big.""" diff --git a/lnbits/extensions/cashu/static/js/base64.js b/lnbits/extensions/cashu/static/js/base64.js index 2cd19a836..b150882f7 100644 --- a/lnbits/extensions/cashu/static/js/base64.js +++ b/lnbits/extensions/cashu/static/js/base64.js @@ -1,40 +1,37 @@ -function unescapeBase64Url (str) { - return (str + '==='.slice((str.length + 3) % 4)) - .replace(/-/g, '+') - .replace(/_/g, '/') - } - - function escapeBase64Url (str) { - return str.replace(/\+/g, '-') - .replace(/\//g, '_') - .replace(/=/g, '') +function unescapeBase64Url(str) { + return (str + '==='.slice((str.length + 3) % 4)) + .replace(/-/g, '+') + .replace(/_/g, '/') +} + +function escapeBase64Url(str) { + return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '') +} + +const uint8ToBase64 = (function (exports) { + 'use strict' + + var fromCharCode = String.fromCharCode + var encode = function encode(uint8array) { + var output = [] + + for (var i = 0, length = uint8array.length; i < length; i++) { + output.push(fromCharCode(uint8array[i])) + } + + return btoa(output.join('')) } - const uint8ToBase64 = (function (exports) { - 'use strict'; - - var fromCharCode = String.fromCharCode; - var encode = function encode(uint8array) { - var output = []; - - for (var i = 0, length = uint8array.length; i < length; i++) { - output.push(fromCharCode(uint8array[i])); - } - - return btoa(output.join('')); - }; - - var asCharCode = function asCharCode(c) { - return c.charCodeAt(0); - }; - - var decode = function decode(chars) { - return Uint8Array.from(atob(chars), asCharCode); - }; - - exports.decode = decode; - exports.encode = encode; - - return exports; - - }({})); \ No newline at end of file + var asCharCode = function asCharCode(c) { + return c.charCodeAt(0) + } + + var decode = function decode(chars) { + return Uint8Array.from(atob(chars), asCharCode) + } + + exports.decode = decode + exports.encode = encode + + return exports +})({}) diff --git a/lnbits/extensions/cashu/templates/cashu/wallet.html b/lnbits/extensions/cashu/templates/cashu/wallet.html index 0d250a629..5da41d0ad 100644 --- a/lnbits/extensions/cashu/templates/cashu/wallet.html +++ b/lnbits/extensions/cashu/templates/cashu/wallet.html @@ -787,7 +787,7 @@ page_container %} const secret = nobleSecp256k1.utils.randomBytes(32) // const secret = nobleSecp256k1.utils.hexToBytes('0000000000000000000000000000000000000000000000000000000000000003') // todo: base64Url - const encodedSecret = uint8ToBase64.encode(secret) + const encodedSecret = uint8ToBase64.encode(secret) secrets.push(encodedSecret) const {B_, randomBlindingFactor} = await step1Bob(secret) randomBlindingFactors.push(randomBlindingFactor) @@ -852,47 +852,45 @@ page_container %} sellTokens: async function () { console.log('#### sell tokens') const amount = this.sellData.invoice.sat - const token = this.tokens - .filter(t => t.promises?.length) - .find(t => t.promises.find(b => b.amount === amount)) - console.log('### token', token) - if (token) { - const promiseIndex = token.promises - .map(p => `${p.amount}`) - .indexOf(`${amount}`) - const promise = token.promises[promiseIndex] - console.log('### promise', promise) + const paidTokens = this.tokens.filter(t => t.promises?.length) + console.log('### paidTokens', paidTokens) + const proofs = paidTokens.map(token => { + // const promiseIndex = token.promises + // .map(p => `${p.amount}`) + // .indexOf(`${amount}`) + return token.promises.map((promise, promiseIndex) => { + // const promise = token.promises[promiseIndex] + console.log('### promise', promise) - const secret = token.secrets[promiseIndex] - const randomBlindingFactor = token.randomBlindingFactors[promiseIndex] + const secret = token.secrets[promiseIndex] + const randomBlindingFactor = + token.randomBlindingFactors[promiseIndex] - const C_ = nobleSecp256k1.Point.fromHex(promise['C_']) - const A = this.keys[promise.amount] // todo + const C_ = nobleSecp256k1.Point.fromHex(promise['C_']) + const A = this.keys[promise.amount] // todo - console.log('#### C_', C_) - console.log('#### A', A) + console.log('#### C_', C_) + console.log('#### A', A) - const C = step3Bob( - C_, - randomBlindingFactor, - nobleSecp256k1.Point.fromHex(A) - ) + const C = step3Bob( + C_, + randomBlindingFactor, + nobleSecp256k1.Point.fromHex(A) + ) - const proofs = [ - { - amount, + return { + amount: promise.amount, secret, C: C.toHex(true) } - ] - - const payload = { - proofs, - amount, - invoice: this.sellData.bolt11 - } - console.log('#### payload', JSON.stringify(payload)) + }) + }) + const payload = { + proofs: proofs.flat(), + amount, + invoice: this.sellData.bolt11 } + console.log('#### payload', JSON.stringify(payload)) }, fetchMintKeys: async function () {