mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-02-22 22:25:47 +01:00
displaying lnurlpay success_actions.
This commit is contained in:
parent
8d135489ab
commit
cf0bd7ece8
6 changed files with 121 additions and 23 deletions
|
@ -1,4 +1,4 @@
|
|||
/* globals windowMixin, decode, Vue, VueQrcodeReader, VueQrcode, Quasar, LNbits, _, EventHub, Chart */
|
||||
/* globals windowMixin, decode, Vue, VueQrcodeReader, VueQrcode, Quasar, LNbits, _, EventHub, Chart, decryptLnurlPayAES */
|
||||
|
||||
Vue.component(VueQrcode.name, VueQrcode)
|
||||
Vue.use(VueQrcodeReader)
|
||||
|
@ -248,7 +248,7 @@ new Vue({
|
|||
var checker = this.parse.paymentChecker
|
||||
setTimeout(() => {
|
||||
clearInterval(checker)
|
||||
}, 1000)
|
||||
}, 10000)
|
||||
},
|
||||
createInvoice: function () {
|
||||
this.receive.status = 'loading'
|
||||
|
@ -469,7 +469,7 @@ new Vue({
|
|||
switch (response.data.success_action.tag) {
|
||||
case 'url':
|
||||
this.$q.notify({
|
||||
message: `<a target="_blank" style="color:inherit" href="${response.data.success_action.url}">${response.data.success_action.url}</a>`,
|
||||
message: `<a target="_blank" style="color: inherit" href="${response.data.success_action.url}">${response.data.success_action.url}</a>`,
|
||||
caption: response.data.success_action.description,
|
||||
html: true,
|
||||
type: 'info',
|
||||
|
@ -486,6 +486,26 @@ new Vue({
|
|||
})
|
||||
break
|
||||
case 'aes':
|
||||
LNbits.api
|
||||
.getPayment(this.g.wallet, response.data.payment_hash)
|
||||
.then(
|
||||
({data: payment}) =>
|
||||
console.log(payment) ||
|
||||
decryptLnurlPayAES(
|
||||
response.data.success_action,
|
||||
payment.preimage
|
||||
)
|
||||
)
|
||||
.then(value => {
|
||||
this.$q.notify({
|
||||
message: value,
|
||||
caption: response.data.success_action.description,
|
||||
html: true,
|
||||
type: 'info',
|
||||
timeout: 0,
|
||||
closeBtn: true
|
||||
})
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
|
@ -211,14 +211,14 @@ async def api_payment(payment_hash):
|
|||
if not payment:
|
||||
return jsonify({"message": "Payment does not exist."}), HTTPStatus.NOT_FOUND
|
||||
elif not payment.pending:
|
||||
return jsonify({"paid": True}), HTTPStatus.OK
|
||||
return jsonify({"paid": True, "preimage": payment.preimage}), HTTPStatus.OK
|
||||
|
||||
try:
|
||||
payment.check_pending()
|
||||
except Exception:
|
||||
return jsonify({"paid": False}), HTTPStatus.OK
|
||||
|
||||
return jsonify({"paid": not payment.pending}), HTTPStatus.OK
|
||||
return jsonify({"paid": not payment.pending, "preimage": payment.preimage}), HTTPStatus.OK
|
||||
|
||||
|
||||
@core_app.route("/api/v1/payments/sse", methods=["GET"])
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
/* globals moment, Vue, EventHub, axios, Quasar, _ */
|
||||
/* globals crypto, moment, Vue, axios, Quasar, _ */
|
||||
|
||||
var LOCALE = 'en'
|
||||
|
||||
var EventHub = new Vue()
|
||||
|
||||
var LNbits = {
|
||||
window.LOCALE = 'en'
|
||||
window.EventHub = new Vue()
|
||||
window.LNbits = {
|
||||
api: {
|
||||
request: function (method, url, apiKey, data) {
|
||||
return axios({
|
||||
|
@ -106,7 +104,7 @@ var LNbits = {
|
|||
)
|
||||
obj.msat = obj.balance
|
||||
obj.sat = Math.round(obj.balance / 1000)
|
||||
obj.fsat = new Intl.NumberFormat(LOCALE).format(obj.sat)
|
||||
obj.fsat = new Intl.NumberFormat(window.LOCALE).format(obj.sat)
|
||||
obj.url = ['/wallet?usr=', obj.user, '&wal=', obj.id].join('')
|
||||
return obj
|
||||
},
|
||||
|
@ -134,7 +132,7 @@ var LNbits = {
|
|||
obj.msat = obj.amount
|
||||
obj.sat = obj.msat / 1000
|
||||
obj.tag = obj.extra.tag
|
||||
obj.fsat = new Intl.NumberFormat(LOCALE).format(obj.sat)
|
||||
obj.fsat = new Intl.NumberFormat(window.LOCALE).format(obj.sat)
|
||||
obj.isIn = obj.amount > 0
|
||||
obj.isOut = obj.amount < 0
|
||||
obj.isPaid = obj.pending === 0
|
||||
|
@ -157,13 +155,13 @@ var LNbits = {
|
|||
})
|
||||
},
|
||||
formatCurrency: function (value, currency) {
|
||||
return new Intl.NumberFormat(LOCALE, {
|
||||
return new Intl.NumberFormat(window.LOCALE, {
|
||||
style: 'currency',
|
||||
currency: currency
|
||||
}).format(value)
|
||||
},
|
||||
formatSat: function (value) {
|
||||
return new Intl.NumberFormat(LOCALE).format(value)
|
||||
return new Intl.NumberFormat(window.LOCALE).format(value)
|
||||
},
|
||||
notifyApiError: function (error) {
|
||||
var types = {
|
||||
|
@ -246,7 +244,7 @@ var LNbits = {
|
|||
}
|
||||
}
|
||||
|
||||
var windowMixin = {
|
||||
window.windowMixin = {
|
||||
data: function () {
|
||||
return {
|
||||
g: {
|
||||
|
@ -276,17 +274,17 @@ var windowMixin = {
|
|||
created: function () {
|
||||
this.$q.dark.set(this.$q.localStorage.getItem('lnbits.darkMode'))
|
||||
if (window.user) {
|
||||
this.g.user = Object.freeze(LNbits.map.user(window.user))
|
||||
this.g.user = Object.freeze(window.LNbits.map.user(window.user))
|
||||
}
|
||||
if (window.wallet) {
|
||||
this.g.wallet = Object.freeze(LNbits.map.wallet(window.wallet))
|
||||
this.g.wallet = Object.freeze(window.LNbits.map.wallet(window.wallet))
|
||||
}
|
||||
if (window.extensions) {
|
||||
var user = this.g.user
|
||||
this.g.extensions = Object.freeze(
|
||||
window.extensions
|
||||
.map(function (data) {
|
||||
return LNbits.map.extension(data)
|
||||
return window.LNbits.map.extension(data)
|
||||
})
|
||||
.map(function (obj) {
|
||||
if (user) {
|
||||
|
@ -303,3 +301,27 @@ var windowMixin = {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.decryptLnurlPayAES = function (success_action, preimage) {
|
||||
let keyb = new Uint8Array(
|
||||
preimage.match(/[\da-f]{2}/gi).map(h => parseInt(h, 16))
|
||||
)
|
||||
|
||||
return crypto.subtle
|
||||
.importKey('raw', keyb, {name: 'AES-CBC', length: 256}, false, ['decrypt'])
|
||||
.then(key => {
|
||||
let ivb = Uint8Array.from(window.atob(success_action.iv), c =>
|
||||
c.charCodeAt(0)
|
||||
)
|
||||
let ciphertextb = Uint8Array.from(
|
||||
window.atob(success_action.ciphertext),
|
||||
c => c.charCodeAt(0)
|
||||
)
|
||||
|
||||
return crypto.subtle.decrypt({name: 'AES-CBC', iv: ivb}, key, ciphertextb)
|
||||
})
|
||||
.then(valueb => {
|
||||
let decoder = new TextDecoder('utf-8')
|
||||
return decoder.decode(valueb)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global Vue, moment, LNbits, EventHub */
|
||||
/* global Vue, moment, LNbits, EventHub, decryptLnurlPayAES */
|
||||
|
||||
Vue.component('lnbits-fsat', {
|
||||
props: {
|
||||
|
@ -199,10 +199,64 @@ Vue.component('lnbits-payment-details', {
|
|||
<div class="col-3"><b>Payment hash</b>:</div>
|
||||
<div class="col-9 text-wrap mono">{{ payment.payment_hash }}</div>
|
||||
</div>
|
||||
<div class="row" v-if="payment.preimage">
|
||||
<div class="row" v-if="hasPreimage">
|
||||
<div class="col-3"><b>Payment proof</b>:</div>
|
||||
<div class="col-9 text-wrap mono">{{ payment.preimage }}</div>
|
||||
</div>
|
||||
<div class="row" v-if="hasSuccessAction">
|
||||
<div class="col-3"><b>Success action</b>:</div>
|
||||
<div class="col-9">
|
||||
<lnbits-lnurlpay-success-action
|
||||
:payment="payment"
|
||||
:success_action="payment.extra.success_action"
|
||||
></lnbits-lnurlpay-success-action>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
`,
|
||||
computed: {
|
||||
hasPreimage() {
|
||||
return (
|
||||
this.payment.preimage &&
|
||||
this.payment.preimage !==
|
||||
'0000000000000000000000000000000000000000000000000000000000000000'
|
||||
)
|
||||
},
|
||||
hasSuccessAction() {
|
||||
return (
|
||||
this.hasPreimage &&
|
||||
this.payment.extra &&
|
||||
this.payment.extra.success_action
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Vue.component('lnbits-lnurlpay-success-action', {
|
||||
props: ['payment', 'success_action'],
|
||||
data() {
|
||||
return {
|
||||
decryptedValue: this.success_action.ciphertext
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<p class="q-mb-sm">{{ success_action.message || success_action.description }}</p>
|
||||
<code v-if="decryptedValue" class="text-h6 q-mt-sm q-mb-none">
|
||||
{{ decryptedValue }}
|
||||
</code>
|
||||
<p v-else-if="success_action.url" class="text-h6 q-mt-sm q-mb-none">
|
||||
<a target="_blank" style="color: inherit;" :href="success_action.url">{{ success_action.url }}</a>
|
||||
</p>
|
||||
</div>
|
||||
`,
|
||||
mounted: function () {
|
||||
if (this.success_action.tag !== 'aes') return null
|
||||
|
||||
decryptLnurlPayAES(this.success_action, this.payment.preimage).then(
|
||||
value => {
|
||||
this.decryptedValue = value
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -34,7 +34,7 @@ class LNPayWallet(Wallet):
|
|||
f"Wallet {data['user_label']} (data['id']) not active, but {data['statusType']['name']}", 0
|
||||
)
|
||||
|
||||
return StatusResponse(None, data["balance"] / 1000)
|
||||
return StatusResponse(None, data["balance"] * 1000)
|
||||
|
||||
def create_invoice(
|
||||
self,
|
||||
|
|
|
@ -29,6 +29,8 @@ class SparkWallet(Wallet):
|
|||
params = args
|
||||
elif kwargs:
|
||||
params = kwargs
|
||||
else:
|
||||
params = {}
|
||||
|
||||
r = httpx.post(self.url + "/rpc", headers={"X-Access": self.token}, json={"method": key, "params": params})
|
||||
try:
|
||||
|
|
Loading…
Add table
Reference in a new issue