This commit is contained in:
callebtc
2022-11-06 03:38:33 +01:00
parent fc45b419ca
commit ff510a4b93

View File

@@ -1,11 +1,13 @@
{% 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 %}
<q-page-container>
<q-page>
<div class="row q-col-gutter-md justify-center q-pt-lg">
<div class="col-12 col-sm-8 col-md-9 col-lg-7 text-center q-gutter-y-md">
<q-scroll-area style="height: 640px; max-width: 1024px;">
<q-scroll-area style="height: 640px; max-width: 1024px">
<div
class="col-12 col-sm-8 col-md-9 col-lg-7 text-center q-gutter-y-md"
>
<q-card class="q-mb-sm">
<q-card-section>
<div class="gt-sm">
@@ -55,11 +57,9 @@
</div>
</div>
</div>
</q-card-section>
</q-card>
<q-card>
<q-card-section>
<div class="row items-center no-wrap q-mb-sm">
@@ -89,8 +89,6 @@
</div>
</div>
<!-- ///////////////////////////////////////////
////////////////// TABLES /////////////////
/////////////////////////////////////////// -->
@@ -100,7 +98,6 @@
<q-tab name="history" label="History"></q-tab>
</q-tabs>
<q-tab-panels v-model="tab">
<!-- ////////////////// TOKEN LIST ///////////////// -->
<q-tab-panel name="tokens">
@@ -172,10 +169,19 @@
</q-badge>
</div>
<div v-if="props.row.status === 'paid'">
<q-icon v-if="props.row.amount>0" name= "call_received" color="green"><q-tooltip>Received</q-tooltip></q-icon>
<q-icon v-if="props.row.amount<0" name= "call_made" color="red"><q-tooltip>Paid</q-tooltip></q-icon>
<q-icon
v-if="props.row.amount>0"
name="call_received"
color="green"
><q-tooltip>Received</q-tooltip></q-icon
>
<q-icon
v-if="props.row.amount<0"
name="call_made"
color="red"
><q-tooltip>Paid</q-tooltip></q-icon
>
<!-- <q-icon name="props.row.amount < 0 ? 'call_made' : 'call_received'" color="green"></q-icon> -->
</div>
</q-td>
<q-td
@@ -238,10 +244,19 @@
</q-badge>
</div>
<div v-if="props.row.status === 'paid'">
<q-icon v-if="props.row.amount>0" name= "call_received" color="green"><q-tooltip>Received</q-tooltip></q-icon>
<q-icon v-if="props.row.amount<0" name= "call_made" color="red"><q-tooltip>Paid</q-tooltip></q-icon>
<q-icon
v-if="props.row.amount>0"
name="call_received"
color="green"
><q-tooltip>Received</q-tooltip></q-icon
>
<q-icon
v-if="props.row.amount<0"
name="call_made"
color="red"
><q-tooltip>Paid</q-tooltip></q-icon
>
<!-- <q-icon name="props.row.amount < 0 ? 'call_made' : 'call_received'" color="green"></q-icon> -->
</div>
</q-td>
<q-td
@@ -263,8 +278,6 @@
{% endraw %}
</q-table>
</q-tab-panel>
</q-tab-panels>
</q-card-section>
</q-card>
@@ -276,7 +289,10 @@
rectangle
color="warning"
outline
@click="showDisclaimerDialog"> Warning</q-btn>
@click="showDisclaimerDialog"
>
Warning</q-btn
>
<q-btn
class="q-mx-sm"
size="10px"
@@ -285,10 +301,11 @@
icon="file_download"
color="warning"
tooltip="asd"
@click="getLocalstorageToFile">Backup<q-tooltip>Download wallet backup</q-tooltip></q-btn>
@click="getLocalstorageToFile"
>Backup<q-tooltip>Download wallet backup</q-tooltip></q-btn
>
</div>
</div>
</q-scroll-area>
<q-tabs
@@ -304,12 +321,12 @@
@click="showInvoicesDialog"
>
</q-tab>
</q-tab>
<q-tab
icon="arrow_upwards"
class="q-pa-none"
label="Pay Invoice"
@click="showParseDialog">
@click="showParseDialog"
>
</q-tab>
<!-- <q-tab icon="photo_camera" label="Scan" @click="showCamera"> </q-tab> -->
</q-tabs>
@@ -336,7 +353,13 @@
</p>
{% endraw %}
<div v-if="canPay" class="row q-mt-lg">
<q-btn unelevated color="primary" :disabled="payInvoiceData.blocking" @click="melt">Pay</q-btn>
<q-btn
unelevated
color="primary"
:disabled="payInvoiceData.blocking"
@click="melt"
>Pay</q-btn
>
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
>Cancel</q-btn
>
@@ -485,7 +508,13 @@
type="submit"
>Enter</q-btn
>
<q-btn unelevated icon="photo_camera" class="q-mx-0" @click="showCamera"> </q-btn>
<q-btn
unelevated
icon="photo_camera"
class="q-mx-0"
@click="showCamera"
>
</q-btn>
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
>Cancel</q-btn
>
@@ -529,27 +558,33 @@
<h6 class="q-my-md text-primary">Warning</h6>
<p>
<strong>Bookmark this page and backup your tokens!</strong>
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.
</p>
<p>
<strong>Add to home screen.</strong>
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.
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.
</p>
<p>
<strong>This service is in BETA!</strong> We hold no responsibility for people losing
access to funds. Use at your own risk!
<strong>This service is in BETA!</strong> We hold no responsibility
for people losing access to funds. Use at your own risk!
</p>
<div class="row q-mt-lg">
<q-btn outline color="grey" @click="copyText(disclaimerDialog.location.href)">Copy wallet URL</q-btn>
<q-btn
outline
color="grey"
@click="copyText(disclaimerDialog.location.href)"
>Copy wallet URL</q-btn
>
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
>I understand</q-btn
>
</div>
</q-card>
</q-dialog>
@@ -602,7 +637,11 @@
color="primary"
>Copy invoice</q-btn
>
<q-btn v-else color="primary" @click="requestMintButton" :disable="!invoiceData.amount > 0"
<q-btn
v-else
color="primary"
@click="requestMintButton"
:disable="!invoiceData.amount > 0"
>Create Invoice</q-btn
>
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
@@ -653,7 +692,7 @@
>
</qrcode>
</q-responsive>
</a>
<!-- </a> -->
</div>
<q-input
outlined
@@ -712,9 +751,7 @@
</div>
<div class="row q-mt-lg">
<q-btn @click="redeem" color="primary"
>Receive Tokens</q-btn
>
<q-btn @click="redeem" color="primary">Receive Tokens</q-btn>
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
>Close</q-btn
>
@@ -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]),
@@ -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()
},
@@ -1674,7 +1710,9 @@
)
this.sendData.tokens = scndProofs
console.log('### this.sendData.tokens', this.sendData.tokens)
this.sendData.tokensBase64 = btoa(JSON.stringify(this.sendData.tokens))
this.sendData.tokensBase64 = btoa(
JSON.stringify(this.sendData.tokens)
)
this.historyTokens.push({
status: 'pending',
@@ -1688,7 +1726,6 @@
console.error(error)
throw error
}
},
checkFees: async function (payment_request) {
const payload = {
@@ -1759,7 +1796,7 @@
amount: -amount,
bolt11: this.payInvoiceData.data.request,
hash: this.payInvoiceData.data.hash,
memo: this.payInvoiceData.data.memo,
memo: this.payInvoiceData.data.memo
})
this.invoicesCashu.push({
amount: -amount,
@@ -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,21 +1856,23 @@
// 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')
}
@@ -1846,7 +1883,7 @@
const tokenJson = atob(token)
const proofs = JSON.parse(tokenJson)
const payload = {
proofs: proofs.flat(),
proofs: proofs.flat()
}
console.log('#### payload', JSON.stringify(payload))
try {
@@ -1865,7 +1902,7 @@
}
}
if (paid) {
console.log("### token paid")
console.log('### token paid')
if (window.navigator.vibrate) navigator.vibrate(200)
this.$q.notify({
timeout: 5000,
@@ -1873,7 +1910,7 @@
message: 'Token paid'
})
} else {
console.log("### token not paid yet")
console.log('### token not paid yet')
if (verbose) {
this.$q.notify({
timeout: 5000,
@@ -1897,10 +1934,12 @@
`/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)
)
},
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -1973,29 +2012,28 @@
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 () {
@@ -2020,9 +2058,8 @@
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)