diff --git a/lnbits/extensions/cashu/static/js/wallet.js b/lnbits/extensions/cashu/static/js/wallet.js
deleted file mode 100644
index 832b075d6..000000000
--- a/lnbits/extensions/cashu/static/js/wallet.js
+++ /dev/null
@@ -1,1104 +0,0 @@
-var currentDateStr = function () {
- return Quasar.utils.date.formatDate(new Date(), 'YYYY-MM-DD HH:mm')
-}
-var mapMint = function (obj) {
- obj.date = Quasar.utils.date.formatDate(
- new Date(obj.time * 1000),
- 'YYYY-MM-DD HH:mm'
- )
- obj.fsat = new Intl.NumberFormat(LOCALE).format(obj.amount)
- obj.cashu = ['/cashu/', obj.id].join('')
- return obj
-}
-
-Vue.component(VueQrcode.name, VueQrcode)
-
-new Vue({
- el: '#vue',
- mixins: [windowMixin],
- data: function () {
- return {
- tickershort: '',
- name: '',
-
- mintId: '',
- mintName: '',
- keys: '',
- invoicesCashu: [],
- invoiceData: {
- amount: 0,
- memo: '',
- bolt11: '',
- hash: ''
- },
- invoiceCheckListener: () => {},
- payInvoiceData: {
- // invoice: '',
- bolt11: '',
- // camera: {
- // show: false,
- // camera: 'auto'
- // }
- show: false,
- invoice: null,
- lnurlpay: null,
- lnurlauth: null,
- data: {
- request: '',
- amount: 0,
- comment: ''
- },
- paymentChecker: null,
- camera: {
- show: false,
- camera: 'auto'
- }
- },
- sendData: {
- amount: 0,
- memo: '',
- tokens: '',
- tokensBase64: ''
- },
- receiveData: {
- tokensBase64: ''
- },
- showInvoiceDetails: false,
- showPayInvoice: false,
- showSendTokens: false,
- showReceiveTokens: false,
- promises: [],
- tokens: [],
- tab: 'tokens',
-
- receive: {
- show: false,
- status: 'pending',
- paymentReq: null,
- paymentHash: null,
- minMax: [0, 2100000000000000],
- lnurl: null,
- units: ['sat'],
- unit: 'sat',
- data: {
- amount: null,
- memo: ''
- }
- },
- parse: {
- show: false,
- invoice: null,
- lnurlpay: null,
- lnurlauth: null,
- data: {
- request: '',
- amount: 0,
- comment: ''
- },
- paymentChecker: null,
- camera: {
- show: false,
- camera: 'auto'
- }
- },
- payments: [],
- invoicesTable: {
- columns: [
- {
- name: 'status',
- align: 'left',
- label: '',
- field: 'status'
- },
- {
- name: 'amount',
- align: 'left',
- label: 'Amount',
- field: 'amount'
- },
- {
- name: 'memo',
- align: 'left',
- label: 'Memo',
- field: 'memo',
- sortable: true
- },
- {
- name: 'date',
- align: 'left',
- label: 'Date',
- field: 'date',
- sortable: true
- },
- {
- name: 'hash',
- align: 'right',
- label: 'Hash',
- field: 'hash',
- sortable: true
- }
- ],
- pagination: {
- sortBy: 'date',
- descending: true,
- rowsPerPage: 5
- },
- filter: null
- },
-
- tokensTable: {
- columns: [
- {
- name: 'value',
- align: 'left',
- label: 'Value ({{LNBITS_DENOMINATION}})',
- field: 'value',
- sortable: true
- },
- {
- name: 'count',
- align: 'left',
- label: 'Count',
- field: 'count',
- sortable: true
- },
- {
- name: 'sum',
- align: 'left',
- label: 'Sum ({{LNBITS_DENOMINATION}})',
- field: 'sum',
- sortable: true
- }
- // {
- // name: 'memo',
- // align: 'left',
- // label: 'Memo',
- // field: 'memo',
- // sortable: true
- // }
- ],
- pagination: {
- rowsPerPage: 5
- },
- filter: null
- },
-
- paymentsChart: {
- show: false
- },
- disclaimerDialog: {
- show: false,
- location: window.location
- },
-
- credit: 0,
- newName: ''
- }
- },
- computed: {
- formattedBalance: function () {
- return this.balance / 100
- },
-
- canPay: function () {
- if (!this.payInvoiceData.invoice) return false
- return this.payInvoiceData.invoice.sat <= this.balance
- },
- pendingPaymentsExist: function () {
- return this.payments.findIndex(payment => payment.pending) !== -1
- },
-
- balance: function () {
- return this.proofs
- .map(t => t)
- .flat()
- .reduce((sum, el) => (sum += el.amount), 0)
- }
- },
- filters: {
- msatoshiFormat: function (value) {
- return LNbits.utils.formatSat(value / 1000)
- }
- },
- methods: {
- getBalance: function () {
- return this.proofs
- .map(t => t)
- .flat()
- .reduce((sum, el) => (sum += el.amount), 0)
- },
- getTokenList: function () {
- const x = this.proofs
- .map(t => t.amount)
- .reduce((acc, amount) => {
- acc[amount] = acc[amount] + amount || 1
- return acc
- }, {})
- return Object.keys(x).map(k => ({
- value: k,
- count: x[k],
- sum: k * x[k]
- }))
- },
-
- paymentTableRowKey: function (row) {
- return row.payment_hash + row.amount
- },
- closeCamera: function () {
- this.payInvoiceData.camera.show = false
- },
- showCamera: function () {
- this.payInvoiceData.camera.show = true
- },
- showChart: function () {
- this.paymentsChart.show = true
- this.$nextTick(() => {
- generateChart(this.$refs.canvas, this.payments)
- })
- },
- focusInput(el) {
- this.$nextTick(() => this.$refs[el].focus())
- },
- showReceiveDialog: function () {
- this.receive.show = true
- this.receive.status = 'pending'
- this.receive.paymentReq = null
- this.receive.paymentHash = null
- this.receive.data.amount = null
- this.receive.data.memo = null
- this.receive.unit = 'sat'
- this.receive.paymentChecker = null
- this.receive.minMax = [0, 2100000000000000]
- this.receive.lnurl = null
- this.focusInput('setAmount')
- },
- showParseDialog: function () {
- this.payInvoiceData.show = true
- this.payInvoiceData.invoice = null
- this.payInvoiceData.lnurlpay = null
- this.payInvoiceData.lnurlauth = null
- this.payInvoiceData.data.request = ''
- this.payInvoiceData.data.comment = ''
- this.payInvoiceData.data.paymentChecker = null
- this.payInvoiceData.camera.show = false
- this.focusInput('pasteInput')
- },
- showDisclaimerDialog: function () {
- this.disclaimerDialog.show = true
- },
-
- closeReceiveDialog: function () {
- setTimeout(() => {
- clearInterval(this.receive.paymentChecker)
- }, 10000)
- },
- closeParseDialog: function () {
- setTimeout(() => {
- clearInterval(this.payInvoiceData.paymentChecker)
- }, 10000)
- },
- onPaymentReceived: function (paymentHash) {
- this.fetchPayments()
- this.fetchBalance()
-
- if (this.receive.paymentHash === paymentHash) {
- this.receive.show = false
- this.receive.paymentHash = null
- clearInterval(this.receive.paymentChecker)
- }
- },
- createInvoice: function () {
- this.receive.status = 'loading'
- if (LNBITS_DENOMINATION != 'sats') {
- this.receive.data.amount = this.receive.data.amount * 100
- }
- LNbits.api
- .createInvoice(
- this.receive.data.amount,
- this.receive.data.memo,
- this.receive.unit,
- this.receive.lnurl && this.receive.lnurl.callback
- )
- .then(response => {
- this.receive.status = 'success'
- this.receive.paymentReq = response.data.payment_request
- this.receive.paymentHash = response.data.payment_hash
-
- if (response.data.lnurl_response !== null) {
- if (response.data.lnurl_response === false) {
- response.data.lnurl_response = `Unable to connect`
- }
-
- if (typeof response.data.lnurl_response === 'string') {
- // failure
- this.$q.notify({
- timeout: 5000,
- type: 'warning',
- message: `${this.receive.lnurl.domain} lnurl-withdraw call failed.`,
- caption: response.data.lnurl_response
- })
- return
- } else if (response.data.lnurl_response === true) {
- // success
- this.$q.notify({
- timeout: 5000,
- message: `Invoice sent to ${this.receive.lnurl.domain}!`,
- spinner: true
- })
- }
- }
-
- clearInterval(this.receive.paymentChecker)
- setTimeout(() => {
- clearInterval(this.receive.paymentChecker)
- }, 40000)
- })
- .catch(err => {
- LNbits.utils.notifyApiError(err)
- this.receive.status = 'pending'
- })
- },
- decodeQR: function (res) {
- this.payInvoiceData.data.request = res
- this.decodeRequest()
- this.payInvoiceData.camera.show = false
- },
- decodeRequest: function () {
- this.payInvoiceData.show = true
- let req = this.payInvoiceData.data.request.toLowerCase()
- if (
- this.payInvoiceData.data.request.toLowerCase().startsWith('lightning:')
- ) {
- this.payInvoiceData.data.request = this.payInvoiceData.data.request.slice(
- 10
- )
- } else if (
- this.payInvoiceData.data.request.toLowerCase().startsWith('lnurl:')
- ) {
- this.payInvoiceData.data.request = this.payInvoiceData.data.request.slice(
- 6
- )
- } else if (req.indexOf('lightning=lnurl1') !== -1) {
- this.payInvoiceData.data.request = this.payInvoiceData.data.request
- .split('lightning=')[1]
- .split('&')[0]
- }
-
- if (
- this.payInvoiceData.data.request.toLowerCase().startsWith('lnurl1') ||
- this.payInvoiceData.data.request.match(/[\w.+-~_]+@[\w.+-~_]/)
- ) {
- return
- }
-
- let invoice
- try {
- invoice = decode(this.payInvoiceData.data.request)
- } catch (error) {
- this.$q.notify({
- timeout: 3000,
- type: 'warning',
- message: error + '.',
- caption: '400 BAD REQUEST'
- })
- this.payInvoiceData.show = false
- throw error
- return
- }
-
- let cleanInvoice = {
- msat: invoice.human_readable_part.amount,
- sat: invoice.human_readable_part.amount / 1000,
- fsat: LNbits.utils.formatSat(invoice.human_readable_part.amount / 1000)
- }
-
- _.each(invoice.data.tags, tag => {
- if (_.isObject(tag) && _.has(tag, 'description')) {
- if (tag.description === 'payment_hash') {
- cleanInvoice.hash = tag.value
- } else if (tag.description === 'description') {
- cleanInvoice.description = tag.value
- } else if (tag.description === 'expiry') {
- var expireDate = new Date(
- (invoice.data.time_stamp + tag.value) * 1000
- )
- cleanInvoice.expireDate = Quasar.utils.date.formatDate(
- expireDate,
- 'YYYY-MM-DDTHH:mm:ss.SSSZ'
- )
- cleanInvoice.expired = false // TODO
- }
- }
- })
-
- this.payInvoiceData.invoice = Object.freeze(cleanInvoice)
- },
- payInvoice: function () {
- let dismissPaymentMsg = this.$q.notify({
- timeout: 0,
- message: 'Processing payment...'
- })
- },
- payLnurl: function () {
- let dismissPaymentMsg = this.$q.notify({
- timeout: 0,
- message: 'Processing payment...'
- })
- },
- authLnurl: function () {
- let dismissAuthMsg = this.$q.notify({
- timeout: 10,
- message: 'Performing authentication...'
- })
- },
-
- deleteWallet: function (walletId, user) {
- LNbits.utils
- .confirmDialog('Are you sure you want to delete this wallet?')
- .onOk(() => {
- LNbits.href.deleteWallet(walletId, user)
- })
- },
- fetchPayments: function () {
- return
- },
- fetchBalance: function () {},
- exportCSV: function () {
- // status is important for export but it is not in paymentsTable
- // because it is manually added with payment detail link and icons
- // and would cause duplication in the list
- let columns = this.paymentsTable.columns
- columns.unshift({
- name: 'pending',
- align: 'left',
- label: 'Pending',
- field: 'pending'
- })
- LNbits.utils.exportCSV(columns, this.payments)
- },
-
- /////////////////////////////////// WALLET ///////////////////////////////////
- showInvoicesDialog: async function () {
- console.log('##### showInvoicesDialog')
- this.invoiceData.amount = 0
- this.invoiceData.bolt11 = ''
- this.invoiceData.hash = ''
- this.invoiceData.memo = ''
- this.showInvoiceDetails = true
- },
-
- showInvoiceDialog: function (data) {
- console.log('##### showInvoiceDialog')
- this.invoiceData = _.clone(data)
- this.showInvoiceDetails = true
- },
-
- showPayInvoiceDialog: function () {
- console.log('### showPayInvoiceDialog')
- this.payInvoiceData.invoice = ''
- this.payInvoiceData.data.request = ''
- this.showPayInvoice = true
- this.payInvoiceData.camera.show = false
- },
-
- showSendTokensDialog: function () {
- this.sendData.tokens = ''
- this.sendData.tokensBase64 = ''
- this.sendData.amount = 0
- this.sendData.memo = ''
- this.showSendTokens = true
- },
-
- showReceiveTokensDialog: function () {
- this.receiveData.tokensBase64 = ''
- this.showReceiveTokens = true
- },
-
- //////////////////////// MINT //////////////////////////////////////////
- requestMintButton: async function () {
- await this.requestMint()
- console.log('this is your invoice BEFORE')
- console.log(this.invoiceData)
- this.invoiceCheckListener = setInterval(async () => {
- try {
- console.log('this is your invoice AFTER')
- console.log(this.invoiceData)
- await this.recheckInvoice(this.invoiceData.hash, false)
- clearInterval(this.invoiceCheckListener)
- this.invoiceData.bolt11 = ''
- this.showInvoiceDetails = false
- navigator.vibrate(200)
- this.$q.notify({
- timeout: 5000,
- type: 'positive',
- message: 'Payment received'
- })
- } catch (error) {
- console.log('not paid yet')
- }
- }, 3000)
- },
-
- requestMint: async function () {
- // gets an invoice from the mint to get new tokens
- try {
- const {data} = await LNbits.api.request(
- 'GET',
- `/cashu/api/v1/${this.mintId}/mint?amount=${this.invoiceData.amount}`
- )
- console.log('### data', data)
-
- this.invoiceData.bolt11 = data.pr
- this.invoiceData.hash = data.hash
- this.invoicesCashu.push({
- ..._.clone(this.invoiceData),
- date: currentDateStr(),
- status: 'pending'
- })
- this.storeinvoicesCashu()
- this.tab = 'invoices'
- return data
- } catch (error) {
- console.error(error)
- LNbits.utils.notifyApiError(error)
- throw error
- }
- },
- mintApi: async function (amounts, payment_hash, verbose = true) {
- console.log('### promises', payment_hash)
- try {
- let secrets = await this.generateSecrets(amounts)
- let {blindedMessages, rs} = await this.constructOutputs(
- amounts,
- secrets
- )
- const promises = await LNbits.api.request(
- 'POST',
- `/cashu/api/v1/${this.mintId}/mint?payment_hash=${payment_hash}`,
- '',
- {
- blinded_messages: blindedMessages
- }
- )
- console.log('### promises data', promises.data)
- let proofs = await this.constructProofs(promises.data, secrets, rs)
- return proofs
- } catch (error) {
- console.error(error)
- if (verbose) {
- LNbits.utils.notifyApiError(error)
- }
- throw error
- }
- },
- mint: async function (amount, payment_hash, verbose = true) {
- try {
- const split = splitAmount(amount)
- const proofs = await this.mintApi(split, payment_hash, verbose)
- if (!proofs.length) {
- throw 'could not mint'
- }
- this.proofs = this.proofs.concat(proofs)
- this.storeProofs()
- await this.setInvoicePaid(payment_hash)
- return proofs
- } catch (error) {
- console.error(error)
- if (verbose) {
- LNbits.utils.notifyApiError(error)
- }
- throw error
- }
- },
- setInvoicePaid: async function (payment_hash) {
- const invoice = this.invoicesCashu.find(i => i.hash === payment_hash)
- invoice.status = 'paid'
- this.storeinvoicesCashu()
- },
- recheckInvoice: async function (payment_hash, verbose = true) {
- console.log('### recheckInvoice.hash', payment_hash)
- const invoice = this.invoicesCashu.find(i => i.hash === payment_hash)
- try {
- proofs = await this.mint(invoice.amount, invoice.hash, verbose)
- return proofs
- } catch (error) {
- console.log('Invoice still pending')
- throw error
- }
- },
-
- generateSecrets: async function (amounts) {
- const secrets = []
- for (let i = 0; i < amounts.length; i++) {
- const secret = nobleSecp256k1.utils.randomBytes(32)
- secrets.push(secret)
- }
- return secrets
- },
-
- constructOutputs: async function (amounts, secrets) {
- const blindedMessages = []
- const rs = []
- for (let i = 0; i < amounts.length; i++) {
- const {B_, r} = await step1Alice(secrets[i])
- blindedMessages.push({amount: amounts[i], B_: B_})
- rs.push(r)
- }
- return {
- blindedMessages,
- rs
- }
- },
-
- constructProofs: function (promises, secrets, rs) {
- const proofs = []
- for (let i = 0; i < promises.length; i++) {
- const encodedSecret = uint8ToBase64.encode(secrets[i])
- let {id, amount, C, secret} = this.promiseToProof(
- promises[i].id,
- promises[i].amount,
- promises[i]['C_'],
- encodedSecret,
- rs[i]
- )
- proofs.push({id, amount, C, secret})
- }
- return proofs
- },
-
- promiseToProof: function (id, amount, C_hex, secret, r) {
- const C_ = nobleSecp256k1.Point.fromHex(C_hex)
- const A = this.keys[amount]
- const C = step3Alice(
- C_,
- nobleSecp256k1.utils.hexToBytes(r),
- nobleSecp256k1.Point.fromHex(A)
- )
- return {
- id,
- amount,
- C: C.toHex(true),
- secret
- }
- },
-
- sumProofs: function (proofs) {
- return proofs.reduce((s, t) => (s += t.amount), 0)
- },
- splitToSend: async function (proofs, amount, invlalidate = false) {
- // splits proofs so the user can keep firstProofs, send scndProofs
- try {
- const spendableProofs = proofs.filter(p => !p.reserved)
- if (this.sumProofs(spendableProofs) < amount) {
- throw new Error('balance too low.')
- }
- let {fristProofs, scndProofs} = await this.split(
- spendableProofs,
- amount
- )
-
- // set scndProofs in this.proofs as reserved
- const usedSecrets = proofs.map(p => p.secret)
- for (let i = 0; i < this.proofs.length; i++) {
- if (usedSecrets.includes(this.proofs[i].secret)) {
- this.proofs[i].reserved = true
- }
- }
- if (invlalidate) {
- // delete tokens from db
- this.proofs = fristProofs
- // add new fristProofs, scndProofs to this.proofs
- this.storeProofs()
- }
-
- return {fristProofs, scndProofs}
- } catch (error) {
- console.error(error)
- LNbits.utils.notifyApiError(error)
- throw error
- }
- },
-
- split: async function (proofs, amount) {
- try {
- if (proofs.length == 0) {
- throw new Error('no proofs provided.')
- }
- let {fristProofs, scndProofs} = await this.splitApi(proofs, amount)
- // delete proofs from this.proofs
- const usedSecrets = proofs.map(p => p.secret)
- this.proofs = this.proofs.filter(p => !usedSecrets.includes(p.secret))
- // add new fristProofs, scndProofs to this.proofs
- this.proofs = this.proofs.concat(fristProofs).concat(scndProofs)
- this.storeProofs()
- return {fristProofs, scndProofs}
- } catch (error) {
- console.error(error)
- LNbits.utils.notifyApiError(error)
- throw error
- }
- },
- splitApi: async function (proofs, amount) {
- try {
- const total = this.sumProofs(proofs)
- const frst_amount = total - amount
- const scnd_amount = amount
- const frst_amounts = splitAmount(frst_amount)
- const scnd_amounts = splitAmount(scnd_amount)
- const amounts = _.clone(frst_amounts)
- amounts.push(...scnd_amounts)
- let secrets = await this.generateSecrets(amounts)
- if (secrets.length != amounts.length) {
- throw new Error('number of secrets does not match number of outputs.')
- }
- let {blindedMessages, rs} = await this.constructOutputs(
- amounts,
- secrets
- )
- const payload = {
- amount,
- proofs,
- outputs: {
- blinded_messages: blindedMessages
- }
- }
-
- console.log('payload', JSON.stringify(payload))
-
- const {data} = await LNbits.api.request(
- 'POST',
- `/cashu/api/v1/${this.mintId}/split`,
- '',
- payload
- )
- const frst_rs = rs.slice(0, frst_amounts.length)
- const frst_secrets = secrets.slice(0, frst_amounts.length)
- const scnd_rs = rs.slice(frst_amounts.length)
- const scnd_secrets = secrets.slice(frst_amounts.length)
- const fristProofs = this.constructProofs(
- data.fst,
- frst_secrets,
- frst_rs
- )
- const scndProofs = this.constructProofs(data.snd, scnd_secrets, scnd_rs)
-
- return {fristProofs, scndProofs}
- } catch (error) {
- console.error(error)
- LNbits.utils.notifyApiError(error)
- throw error
- }
- },
-
- redeem: async function () {
- this.showReceiveTokens = false
- console.log('### receive tokens', this.receiveData.tokensBase64)
- try {
- if (this.receiveData.tokensBase64.length == 0) {
- throw new Error('no tokens provided.')
- }
- const tokensJson = atob(this.receiveData.tokensBase64)
- const proofs = JSON.parse(tokensJson)
- const amount = proofs.reduce((s, t) => (s += t.amount), 0)
- let {fristProofs, scndProofs} = await this.split(proofs, amount)
- // HACK: we need to do this so the balance updates
- this.proofs = this.proofs.concat([])
- navigator.vibrate(200)
- this.$q.notify({
- timeout: 5000,
- type: 'positive',
- message: 'Tokens received'
- })
- } catch (error) {
- console.error(error)
- LNbits.utils.notifyApiError(error)
- throw error
- }
- // }
- },
-
- sendTokens: async function () {
- // keep firstProofs, send scndProofs
- let {fristProofs, scndProofs} = await this.splitToSend(
- this.proofs,
- this.sendData.amount,
- true
- )
- this.sendData.tokens = ''
- this.sendData.tokensBase64 = ''
- this.sendData.tokens = scndProofs
- console.log('### this.sendData.tokens', this.sendData.tokens)
- this.sendData.tokensBase64 = btoa(JSON.stringify(this.sendData.tokens))
- navigator.vibrate(200)
- },
- checkFees: async function (payment_request) {
- const payload = {
- pr: payment_request
- }
- console.log('#### payload', JSON.stringify(payload))
- try {
- const {data} = await LNbits.api.request(
- 'POST',
- `/cashu/api/v1/${this.mintId}/checkfees`,
- '',
- payload
- )
- console.log('#### checkFees', payment_request, data.fee)
- return data.fee
- } catch (error) {
- console.error(error)
- LNbits.utils.notifyApiError(error)
- throw error
- }
- },
- melt: async function () {
- // todo: get fees from server and add to inputs
- console.log('#### pay lightning')
- const amount_invoice = this.payInvoiceData.invoice.sat
- const amount =
- amount_invoice +
- (await this.checkFees(this.payInvoiceData.data.request))
- console.log(
- '#### amount invoice',
- amount_invoice,
- 'amount with fees',
- amount
- )
- // if (amount > balance()) {
- // LNbits.utils.notifyApiError('Balance too low')
- // return
- // }
- let {fristProofs, scndProofs} = await this.splitToSend(
- this.proofs,
- amount
- )
- const payload = {
- proofs: scndProofs.flat(),
- amount,
- invoice: this.payInvoiceData.data.request
- }
- console.log('#### payload', JSON.stringify(payload))
- try {
- const {data} = await LNbits.api.request(
- 'POST',
- `/cashu/api/v1/${this.mintId}/melt`,
- '',
- payload
- )
- navigator.vibrate(200)
- this.$q.notify({
- timeout: 5000,
- type: 'positive',
- message: 'Invoice paid'
- })
- // delete tokens from db
- this.proofs = fristProofs
- // add new fristProofs, scndProofs to this.proofs
- this.storeProofs()
- console.log({
- 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,
- hash: this.payInvoiceData.data.hash,
- memo: this.payInvoiceData.data.memo,
- date: currentDateStr(),
- status: 'paid'
- })
- this.storeinvoicesCashu()
- this.tab = 'invoices'
-
- this.payInvoiceData.invoice = false
- this.payInvoiceData.show = false
- } catch (error) {
- console.error(error)
- LNbits.utils.notifyApiError(error)
- throw error
- }
- },
-
- recheckPendingInvoices: async function () {
- for (const invoice of this.invoicesCashu) {
- if (invoice.status === 'pending' && invoice.sat > 0) {
- this.recheckInvoice(invoice.hash, false)
- }
- }
- },
-
- fetchMintKeys: async function () {
- const {data} = await LNbits.api.request(
- 'GET',
- `/cashu/api/v1/${this.mintId}/keys`
- )
- this.keys = data
- localStorage.setItem(
- this.mintKey(this.mintId, 'keys'),
- JSON.stringify(data)
- )
- },
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- findTokenForAmount: function (amount) {
- for (const token of this.proofs) {
- const index = token.promises?.findIndex(p => p.amount === amount)
- if (index >= 0) {
- return {
- promise: token.promises[index],
- secret: token.secrets[index],
- r: token.rs[index]
- }
- }
- }
- },
-
- checkInvoice: function () {
- console.log('#### checkInvoice')
- try {
- const invoice = decode(this.payInvoiceData.data.request)
-
- const cleanInvoice = {
- msat: invoice.human_readable_part.amount,
- sat: invoice.human_readable_part.amount / 1000,
- fsat: LNbits.utils.formatSat(
- invoice.human_readable_part.amount / 1000
- )
- }
-
- _.each(invoice.data.tags, tag => {
- if (_.isObject(tag) && _.has(tag, 'description')) {
- if (tag.description === 'payment_hash') {
- cleanInvoice.hash = tag.value
- } else if (tag.description === 'description') {
- cleanInvoice.description = tag.value
- } else if (tag.description === 'expiry') {
- var expireDate = new Date(
- (invoice.data.time_stamp + tag.value) * 1000
- )
- cleanInvoice.expireDate = Quasar.utils.date.formatDate(
- expireDate,
- 'YYYY-MM-DDTHH:mm:ss.SSSZ'
- )
- cleanInvoice.expired = false // TODO
- }
- }
-
- this.payInvoiceData.invoice = cleanInvoice
- })
-
- console.log(
- '#### this.payInvoiceData.invoice',
- this.payInvoiceData.invoice
- )
- } catch (error) {
- this.$q.notify({
- timeout: 5000,
- type: 'warning',
- message: 'Could not decode invoice',
- caption: error + ''
- })
- throw error
- }
- },
-
- storeinvoicesCashu: function () {
- localStorage.setItem(
- this.mintKey(this.mintId, 'invoicesCashu'),
- JSON.stringify(this.invoicesCashu)
- )
- },
- storeProofs: function () {
- localStorage.setItem(
- this.mintKey(this.mintId, 'proofs'),
- JSON.stringify(this.proofs, bigIntStringify)
- )
- },
-
- mintKey: function (mintId, key) {
- // returns a key for the local storage
- // depending on the current mint
- return 'cashu.' + mintId + '.' + key
- }
- },
- watch: {
- payments: function () {
- this.balance()
- }
- },
-
- created: function () {
- let params = new URL(document.location).searchParams
-
- // get mint
- if (params.get('mint_id')) {
- this.mintId = params.get('mint_id')
- this.$q.localStorage.set('cashu.mint', params.get('mint_id'))
- } else if (this.$q.localStorage.getItem('cashu.mint')) {
- this.mintId = this.$q.localStorage.getItem('cashu.mint')
- } else {
- this.$q.notify({
- color: 'red',
- message: 'No mint set!'
- })
- }
-
- // get name
- if (params.get('mint_name')) {
- this.mintName = params.get('mint_name')
- 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')
- }
-
- // get ticker
- if (
- !params.get('tsh') &&
- !this.$q.localStorage.getItem(this.mintKey(this.mintId, 'tickershort'))
- ) {
- 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.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')
- )
- }
-
- const keysJson = localStorage.getItem(this.mintKey(this.mintId, 'keys'))
- if (!keysJson) {
- this.fetchMintKeys()
- } else {
- this.keys = JSON.parse(keysJson)
- }
-
- this.invoicesCashu = JSON.parse(
- localStorage.getItem(this.mintKey(this.mintId, 'invoicesCashu')) || '[]'
- )
- 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)
- console.log('#### this.mintName', this.mintName)
-
- this.recheckPendingInvoices()
- }
-})
diff --git a/lnbits/extensions/cashu/templates/cashu/wallet.html b/lnbits/extensions/cashu/templates/cashu/wallet.html
index 7ec994372..88af72caf 100644
--- a/lnbits/extensions/cashu/templates/cashu/wallet.html
+++ b/lnbits/extensions/cashu/templates/cashu/wallet.html
@@ -625,5 +625,1107 @@
-
+
{% endblock %}