diff --git a/lnbits/extensions/cashu/templates/cashu/wallet.html b/lnbits/extensions/cashu/templates/cashu/wallet.html index 7ad093436..73549fc73 100644 --- a/lnbits/extensions/cashu/templates/cashu/wallet.html +++ b/lnbits/extensions/cashu/templates/cashu/wallet.html @@ -1,295 +1,312 @@ -{% extends "public.html" %} {% block toolbar_title %} {% raw %} {{name}} Cashu {% endraw %} {% endblock %} -{% block footer %}{% endblock %} -{% block page_container %} +{% extends "public.html" %} {% block toolbar_title %} {% raw %} {{name}} Cashu +{% endraw %} {% endblock %} {% block footer %}{% endblock %} {% block +page_container %}
-
- - - -
-
-
- Receive invoice - + +
+ + +
+
+
+ Receive invoice + +
+
+

+
+ {% raw %} {{getBalance()}} + {{tickershort}}{% endraw %} +
+

+
+
+ Pay invoice + +
-
-

-
- {% raw %} {{getBalance()}} - {{tickershort}}{% endraw %} -
-

+
+
+
+
+

+
+ {% raw %} {{getBalance()}} + {{tickershort}}{% endraw %} +
+

+
-
+
+ + + + + +
+
Pay invoice - + @click="showReceiveTokensDialog" + >Receive Tokens +
+
+
+ + Send Tokens
-
-
-
-
-

-
- {% raw %} {{getBalance()}} - {{tickershort}}{% endraw %} -
-

-
-
-
- - - - - - -
-
- Receive Tokens -
-
-
- - Send Tokens -
-
- - - - - - - - - - + + + + + + + - + + + {% raw %} + + {% endraw %} + + - - - {% raw %} - - {% endraw %} - - + - + + + {% raw %} + + {% endraw %} + + - - - {% raw %} - + {% endraw %} + + + +
+
- - - - - -
- Warning - BackupDownload wallet backup +
+ + Warning + BackupDownload wallet backup +
-
- - + - - + @@ -336,7 +353,13 @@

{% endraw %}
- Pay + Pay Cancel @@ -485,7 +508,13 @@ type="submit" >Enter - + + Cancel @@ -529,27 +558,33 @@
Warning

Bookmark this page and backup your tokens! - Ecash is a bearer asset, meaning losing access to this wallet will mean you will - lose the funds. This wallet stores ecash tokens in its database. If you lose the link or delete your - your data without backing up, you will lose your tokens. Press the Backup button to download - a copy of your tokens. + Ecash is a bearer asset, meaning losing access to this wallet will + mean you will lose the funds. This wallet stores ecash tokens in its + database. If you lose the link or delete your your data without + backing up, you will lose your tokens. Press the Backup button to + download a copy of your tokens.

-

- Add to home screen. - You can add Cashu to your home screen as a progressive web app (PWA). - On Android Chrome, click the hamburger menu at the upper right. - On iOS Safari, click the share button. Now press the Add to Home screen button. -

-

- This service is in BETA! We hold no responsibility for people losing - access to funds. Use at your own risk! +

+ Add to home screen. + You can add Cashu to your home screen as a progressive web app + (PWA). On Android Chrome, click the hamburger menu at the upper + right. On iOS Safari, click the share button. Now press the Add to + Home screen button. +

+

+ This service is in BETA! We hold no responsibility + for people losing access to funds. Use at your own risk!

- Copy wallet URL - Copy wallet URL + I understand -
@@ -602,7 +637,11 @@ color="primary" >Copy invoice - Create Invoice
- - - - - + + + + +
- Receive Tokens + Receive Tokens Close @@ -930,7 +967,7 @@ label: 'Payment request', field: 'bolt11', sortable: false - }, + }, { name: 'hash', align: 'left', @@ -949,13 +986,13 @@ historyTable: { columns: [ - { + { name: 'status', align: 'left', label: '', field: 'status', sortable: true - }, + }, { name: 'amount', align: 'left', @@ -1033,12 +1070,12 @@ getTokenList: function () { console.log(this.proofs) const amounts = this.proofs.map(t => t.amount) - const counts = {}; + const counts = {} for (const num of amounts) { - counts[num] = counts[num] ? counts[num] + 1 : 1; + counts[num] = counts[num] ? counts[num] + 1 : 1 } - console.log("counts", counts) + console.log('counts', counts) return Object.keys(counts).map(k => ({ value: parseInt(k), count: parseInt(counts[k]), @@ -1088,7 +1125,7 @@ this.payInvoiceData.camera.show = false this.focusInput('pasteInput') }, - showDisclaimerDialog: function() { + showDisclaimerDialog: function () { this.disclaimerDialog.show = true }, @@ -1315,11 +1352,11 @@ showTokenDialog: function (token) { console.log('##### showTokenDialog') // TODO: this must be decoded and desiarlized! - this.sendData.tokens = _.clone(token) - this.sendData.tokensBase64 = _.clone(token) + this.sendData.tokens = _.clone(token) + this.sendData.tokensBase64 = _.clone(token) this.showSendTokens = true // kick off token check worker - this.checkTokenSpendableWorker() + this.checkTokenSpendableWorker() }, showSendTokensDialog: function () { @@ -1397,7 +1434,6 @@ return proofs.reduce((s, t) => (s += t.amount), 0) }, - //////////// API /////////// invoiceCheckWorker: async function () { @@ -1408,7 +1444,7 @@ // exit loop after 2m if (nInterval > 40) { - console.log("### stopping invoice check worker") + console.log('### stopping invoice check worker') clearInterval(this.invoiceCheckListener) } console.log('### setInterval', nInterval) @@ -1418,7 +1454,7 @@ await this.recheckInvoice(this.invoiceData.hash, false) // only without error (invoice paid) will we reach here - console.log("### stopping invoice check worker") + console.log('### stopping invoice check worker') clearInterval(this.invoiceCheckListener) this.invoiceData.bolt11 = '' this.showInvoiceDetails = false @@ -1436,7 +1472,7 @@ requestMintButton: async function () { await this.requestMint() - console.log("#### request mint", this.invoiceData) + console.log('#### request mint', this.invoiceData) await this.invoiceCheckWorker() }, @@ -1666,17 +1702,19 @@ sendTokens: async function () { try { - // keep firstProofs, send scndProofs - let {fristProofs, scndProofs} = await this.splitToSend( - this.proofs, - this.sendData.amount, - true - ) - this.sendData.tokens = scndProofs - console.log('### this.sendData.tokens', this.sendData.tokens) - this.sendData.tokensBase64 = btoa(JSON.stringify(this.sendData.tokens)) + // keep firstProofs, send scndProofs + let {fristProofs, scndProofs} = await this.splitToSend( + this.proofs, + this.sendData.amount, + true + ) + this.sendData.tokens = scndProofs + console.log('### this.sendData.tokens', this.sendData.tokens) + this.sendData.tokensBase64 = btoa( + JSON.stringify(this.sendData.tokens) + ) - this.historyTokens.push({ + this.historyTokens.push({ status: 'pending', amount: -this.sendData.amount, date: currentDateStr(), @@ -1688,7 +1726,6 @@ console.error(error) throw error } - }, checkFees: async function (payment_request) { const payload = { @@ -1756,11 +1793,11 @@ this.proofs = fristProofs this.storeProofs() console.log({ - amount: -amount, - bolt11: this.payInvoiceData.data.request, - hash: this.payInvoiceData.data.hash, - memo: this.payInvoiceData.data.memo, - }) + amount: -amount, + bolt11: this.payInvoiceData.data.request, + hash: this.payInvoiceData.data.hash, + memo: this.payInvoiceData.data.memo + }) this.invoicesCashu.push({ amount: -amount, bolt11: this.payInvoiceData.data.request, @@ -1775,7 +1812,6 @@ this.payInvoiceData.invoice = false this.payInvoiceData.show = false this.payInvoiceData.blocking = false - } catch (error) { this.payInvoiceData.blocking = false console.error(error) @@ -1812,7 +1848,6 @@ this.storehistoryTokens() }, - checkTokenSpendableWorker: async function () { let nInterval = 0 this.tokensCheckSpendableListener = setInterval(async () => { @@ -1821,32 +1856,34 @@ // exit loop after 2m if (nInterval > 24) { - console.log("### stopping token check worker") + console.log('### stopping token check worker') clearInterval(this.tokensCheckSpendableListener) } console.log('### setInterval', nInterval) console.log(this.sendData) // this will throw an error if the invoice is pending - paid = await this.checkTokenSpendable(this.sendData.tokensBase64, false) + paid = await this.checkTokenSpendable( + this.sendData.tokensBase64, + false + ) if (paid) { - console.log("### stopping token check worker") + console.log('### stopping token check worker') clearInterval(this.tokensCheckSpendableListener) this.sendData.tokens = '' this.showSendTokens = false } - } catch (error) { console.log('not paid yet') } }, 5000) }, - checkTokenSpendable: async function(token, verbose=true) { + checkTokenSpendable: async function (token, verbose = true) { const tokenJson = atob(token) const proofs = JSON.parse(tokenJson) const payload = { - proofs: proofs.flat(), + proofs: proofs.flat() } console.log('#### payload', JSON.stringify(payload)) try { @@ -1859,13 +1896,13 @@ // iterate through response of form {0: true, 1: false, ...} let paid = false for (const [key, spendable] of Object.entries(data)) { - if (!spendable){ - this.setTokenPaid(token) - paid = true - } + if (!spendable) { + this.setTokenPaid(token) + paid = true + } } - if (paid){ - console.log("### token paid") + if (paid) { + console.log('### token paid') if (window.navigator.vibrate) navigator.vibrate(200) this.$q.notify({ timeout: 5000, @@ -1873,13 +1910,13 @@ message: 'Token paid' }) } else { - console.log("### token not paid yet") + console.log('### token not paid yet') if (verbose) { this.$q.notify({ - timeout: 5000, - color: 'grey', - message: 'Token still pending' - }) + timeout: 5000, + color: 'grey', + message: 'Token still pending' + }) } this.sendData.tokens = token } @@ -1888,7 +1925,7 @@ console.error(error) LNbits.utils.notifyApiError(error) throw error - } + } }, fetchMintKeys: async function () { @@ -1897,9 +1934,11 @@ `/cashu/api/v1/${this.mintId}/keys` ) this.keys = data - localStorage.setItem(this.mintKey(this.mintId, 'keys'), JSON.stringify(data)) - }, - + localStorage.setItem( + this.mintKey(this.mintId, 'keys'), + JSON.stringify(data) + ) + }, //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1970,32 +2009,31 @@ ////////////// STORAGE ///////////// - getLocalstorageToFile: async function() { + getLocalstorageToFile: async function () { // https://stackoverflow.com/questions/24263682/save-restore-local-storage-to-a-local-file const fileName = `cashu_backup_${currentDateStr()}.json` - var a = {}; + var a = {} for (var i = 0; i < localStorage.length; i++) { - var k = localStorage.key(i); - var v = localStorage.getItem(k); - a[k] = v; + var k = localStorage.key(i) + var v = localStorage.getItem(k) + a[k] = v } var textToSave = JSON.stringify(a) var textToSaveAsBlob = new Blob([textToSave], { - type: "text/plain" - }); - var textToSaveAsURL = window.URL.createObjectURL(textToSaveAsBlob); + type: 'text/plain' + }) + var textToSaveAsURL = window.URL.createObjectURL(textToSaveAsBlob) - var downloadLink = document.createElement("a"); - downloadLink.download = fileName; - downloadLink.innerHTML = "Download File"; - downloadLink.href = textToSaveAsURL; + var downloadLink = document.createElement('a') + downloadLink.download = fileName + downloadLink.innerHTML = 'Download File' + downloadLink.href = textToSaveAsURL downloadLink.onclick = function () { - document.body.removeChild(event.target); - }; - downloadLink.style.display = "none"; - document.body.appendChild(downloadLink); - downloadLink.click(); - + document.body.removeChild(event.target) + } + downloadLink.style.display = 'none' + document.body.appendChild(downloadLink) + downloadLink.click() }, storeinvoicesCashu: function () { @@ -2009,20 +2047,19 @@ this.mintKey(this.mintId, 'historyTokens'), JSON.stringify(this.historyTokens) ) - }, + }, storeProofs: function () { localStorage.setItem( this.mintKey(this.mintId, 'proofs'), JSON.stringify(this.proofs, bigIntStringify) ) }, - - mintKey: function(mintId, key) { + + mintKey: function (mintId, key) { // returns a key for the local storage // depending on the current mint - return "cashu." + mintId + "." + key - }, - + return 'cashu.' + mintId + '.' + key + } }, watch: { payments: function () { @@ -2049,7 +2086,10 @@ // get name if (params.get('mint_name')) { this.mintName = params.get('mint_name') - this.$q.localStorage.set(this.mintKey(this.mintId, 'mintName'), this.mintName) + this.$q.localStorage.set( + this.mintKey(this.mintId, 'mintName'), + this.mintName + ) } else if (this.$q.localStorage.getItem('cashu.name')) { this.mintName = this.$q.localStorage.getItem('cashu.name') } @@ -2059,13 +2099,23 @@ !params.get('tsh') && !this.$q.localStorage.getItem(this.mintKey(this.mintId, 'tickershort')) ) { - this.$q.localStorage.set(this.mintKey(this.mintId, 'tickershort'), 'sats') + this.$q.localStorage.set( + this.mintKey(this.mintId, 'tickershort'), + 'sats' + ) this.tickershort = 'sats' } else if (params.get('tsh')) { - this.$q.localStorage.set(this.mintKey(this.mintId, 'tickershort'), params.get('tsh')) + this.$q.localStorage.set( + this.mintKey(this.mintId, 'tickershort'), + params.get('tsh') + ) this.tickershort = params.get('tsh') - } else if (this.$q.localStorage.getItem(this.mintKey(this.mintId, 'tickershort'))) { - this.tickershort = this.$q.localStorage.getItem(this.mintKey(this.mintId, 'tickershort')) + } else if ( + this.$q.localStorage.getItem(this.mintKey(this.mintId, 'tickershort')) + ) { + this.tickershort = this.$q.localStorage.getItem( + this.mintKey(this.mintId, 'tickershort') + ) } const keysJson = localStorage.getItem(this.mintKey(this.mintId, 'keys')) @@ -2083,7 +2133,9 @@ localStorage.getItem(this.mintKey(this.mintId, 'historyTokens')) || '[]' ) - this.proofs = JSON.parse(localStorage.getItem(this.mintKey(this.mintId, 'proofs')) || '[]') + this.proofs = JSON.parse( + localStorage.getItem(this.mintKey(this.mintId, 'proofs')) || '[]' + ) console.log('### invoicesCashu', this.invoicesCashu) console.table('### tokens', this.proofs) console.log('#### this.mintId', this.mintId)