mirror of
https://github.com/lnbits/lnbits.git
synced 2025-06-27 01:01:02 +02:00
feat: add web-socket to mempool; & replace UI mappings
This commit is contained in:
parent
d74b48b0b6
commit
912a7e1c4b
@ -3,7 +3,9 @@
|
|||||||
<q-card class="my-card">
|
<q-card class="my-card">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<center>
|
<center>
|
||||||
<div class="col theHeading">{{ charge.description }}</div>
|
<div class="col theHeading">
|
||||||
|
<span v-text="charge.description"></span>
|
||||||
|
</div>
|
||||||
</center>
|
</center>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div
|
<div
|
||||||
@ -39,18 +41,32 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col" style="margin: 2px 15px; max-height: 100px">
|
<div class="col" style="margin: 2px 15px; max-height: 100px">
|
||||||
<center>
|
<div class="row items-center q-mt-md">
|
||||||
<q-btn flat dense outline @click="copyText('{{ charge.id }}')"
|
<div class="col-4 q-pr-lg">Charge Id:</div>
|
||||||
>Charge ID: {{ charge.id }}</q-btn
|
<div class="col-8 q-pr-lg">
|
||||||
>
|
<q-btn flat dense outline @click="copyText(charge.id)"
|
||||||
</center>
|
><span v-text="charge.id"></span
|
||||||
<span
|
></q-btn>
|
||||||
><small
|
</div>
|
||||||
>{% raw %} Total to pay: {{ charge.amount }}sats<br />
|
</div>
|
||||||
Amount paid: {{ charge.balance }}</small
|
<div class="row items-center q-mt-md">
|
||||||
><br />
|
<div class="col-4 q-pr-lg">Total to pay:</div>
|
||||||
Amount due: {{ charge.amount - charge.balance }}sats {% endraw %}
|
<div class="col-8 q-pr-lg">
|
||||||
</span>
|
<span v-text="charge.amount"></span> sats
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row items-center q-mt-md">
|
||||||
|
<div class="col-4 q-pr-lg">Amount paid:</div>
|
||||||
|
<div class="col-8 q-pr-lg">
|
||||||
|
<span v-text="charge.balance"></span> sats
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row items-center q-mt-md">
|
||||||
|
<div class="col-4 q-pr-lg">Amount due:</div>
|
||||||
|
<div class="col-8 q-pr-lg">
|
||||||
|
<span v-text="charge.amount - charge.balance"></span> sats
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<q-separator></q-separator>
|
<q-separator></q-separator>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
@ -119,23 +135,22 @@
|
|||||||
></q-icon>
|
></q-icon>
|
||||||
<q-btn
|
<q-btn
|
||||||
outline
|
outline
|
||||||
v-if="'{{ charge.webhook }}' != 'None'"
|
v-if="charge.webhook"
|
||||||
type="a"
|
type="a"
|
||||||
href="{{ charge.completelink }}"
|
:href="charge.completelink"
|
||||||
label="{{ charge.completelinktext }}"
|
:label="charge.completelinktext"
|
||||||
></q-btn>
|
></q-btn>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<center>
|
<span class="text-subtitle2"
|
||||||
<span class="text-subtitle2"
|
>Pay this lightning-network invoice:</span
|
||||||
>Pay this <br />
|
>
|
||||||
lightning-network invoice</span
|
<br />
|
||||||
>
|
|
||||||
</center>
|
<a :href="'lightning:'+charge.payment_request">
|
||||||
<a href="lightning:{{ charge.payment_request }}">
|
|
||||||
<q-responsive :ratio="1" class="q-mx-md">
|
<q-responsive :ratio="1" class="q-mx-md">
|
||||||
<qrcode
|
<qrcode
|
||||||
:value="'{{ charge.payment_request }}'"
|
:value="charge.payment_request"
|
||||||
:options="{width: 800}"
|
:options="{width: 800}"
|
||||||
class="rounded-borders"
|
class="rounded-borders"
|
||||||
></qrcode>
|
></qrcode>
|
||||||
@ -145,7 +160,7 @@
|
|||||||
<q-btn
|
<q-btn
|
||||||
outline
|
outline
|
||||||
color="grey"
|
color="grey"
|
||||||
@click="copyText('{{ charge.payment_request }}')"
|
@click="copyText(charge.payment_request)"
|
||||||
>Copy invoice</q-btn
|
>Copy invoice</q-btn
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@ -169,23 +184,23 @@
|
|||||||
></q-icon>
|
></q-icon>
|
||||||
<q-btn
|
<q-btn
|
||||||
outline
|
outline
|
||||||
v-if="'{{ charge.webhook }}' != None"
|
v-if="charge.webhook "
|
||||||
type="a"
|
type="a"
|
||||||
href="{{ charge.completelink }}"
|
:href="charge.completelink"
|
||||||
label="{{ charge.completelinktext }}"
|
:label="charge.completelinktext"
|
||||||
></q-btn>
|
></q-btn>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<center>
|
<span class="text-subtitle2"
|
||||||
<span class="text-subtitle2"
|
>Send
|
||||||
>Send {{ charge.amount }}sats<br />
|
<span v-text="charge.amount"></span>
|
||||||
to this onchain address</span
|
sats to this onchain address</span
|
||||||
>
|
>
|
||||||
</center>
|
|
||||||
<a href="bitcoin:{{ charge.onchainaddress }}">
|
<a :href="'bitcoin:'+charge.onchainaddress">
|
||||||
<q-responsive :ratio="1" class="q-mx-md">
|
<q-responsive :ratio="1" class="q-mx-md">
|
||||||
<qrcode
|
<qrcode
|
||||||
:value="'{{ charge.onchainaddress }}'"
|
:value="charge.onchainaddress"
|
||||||
:options="{width: 800}"
|
:options="{width: 800}"
|
||||||
class="rounded-borders"
|
class="rounded-borders"
|
||||||
></qrcode>
|
></qrcode>
|
||||||
@ -195,7 +210,7 @@
|
|||||||
<q-btn
|
<q-btn
|
||||||
outline
|
outline
|
||||||
color="grey"
|
color="grey"
|
||||||
@click="copyText('{{ charge.onchainaddress }}')"
|
@click="copyText(charge.onchainaddress)"
|
||||||
>Copy address</q-btn
|
>Copy address</q-btn
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@ -210,7 +225,7 @@
|
|||||||
|
|
||||||
<style>
|
<style>
|
||||||
.theCard {
|
.theCard {
|
||||||
width: 360px;
|
width: 30%;
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
}
|
}
|
||||||
.theHeading {
|
.theHeading {
|
||||||
@ -220,6 +235,7 @@
|
|||||||
</style>
|
</style>
|
||||||
<!-- todo: use config mempool -->
|
<!-- todo: use config mempool -->
|
||||||
<script src="https://mempool.space/mempool.js"></script>
|
<script src="https://mempool.space/mempool.js"></script>
|
||||||
|
<script src="{{ url_for('satspay_static', path='js/utils.js') }}"></script>
|
||||||
<script>
|
<script>
|
||||||
Vue.component(VueQrcode.name, VueQrcode)
|
Vue.component(VueQrcode.name, VueQrcode)
|
||||||
|
|
||||||
@ -228,7 +244,8 @@
|
|||||||
mixins: [windowMixin],
|
mixins: [windowMixin],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
charge: JSON.parse('{{charge | tojson}}'),
|
charge: JSON.parse('{{charge_data | tojson}}'),
|
||||||
|
ws: null,
|
||||||
newProgress: 0.4,
|
newProgress: 0.4,
|
||||||
counter: 1,
|
counter: 1,
|
||||||
newTimeLeft: '',
|
newTimeLeft: '',
|
||||||
@ -277,11 +294,13 @@
|
|||||||
|
|
||||||
const fn = async () =>
|
const fn = async () =>
|
||||||
addressesAPI.getAddressTxsUtxo({
|
addressesAPI.getAddressTxsUtxo({
|
||||||
address: charge.onchainaddress
|
address: this.charge.onchainaddress
|
||||||
})
|
})
|
||||||
|
|
||||||
const utxos = await retryWithDelay(fn)
|
const utxos = await retryWithDelay(fn)
|
||||||
charge.balance = utxos.reduce((t, u) => t + u.value, 0)
|
console.log('### utxos', utxos)
|
||||||
|
this.charge.balance = utxos.reduce((t, u) => t + u.value, 0)
|
||||||
|
console.log('### utxos', utxos)
|
||||||
},
|
},
|
||||||
payInvoice: function () {
|
payInvoice: function () {
|
||||||
this.lnbtc = true
|
this.lnbtc = true
|
||||||
@ -293,8 +312,8 @@
|
|||||||
},
|
},
|
||||||
refreshExpirationTime: function () {
|
refreshExpirationTime: function () {
|
||||||
this.timetoComplete =
|
this.timetoComplete =
|
||||||
parseInt('{{ charge.time }}') * 60 -
|
parseInt(this.charge.time) * 60 -
|
||||||
(Date.now() / 1000 - parseInt('{{ charge.timestamp }}'))
|
(Date.now() / 1000 - parseInt(this.charge.timestamp))
|
||||||
|
|
||||||
this.newTimeLeft = Quasar.utils.date.formatDate(
|
this.newTimeLeft = Quasar.utils.date.formatDate(
|
||||||
new Date((this.timeToComplete - 3600) * 1000),
|
new Date((this.timeToComplete - 3600) * 1000),
|
||||||
@ -304,7 +323,7 @@
|
|||||||
refreshProgres: function () {
|
refreshProgres: function () {
|
||||||
this.refreshExpirationTime()
|
this.refreshExpirationTime()
|
||||||
this.newProgress =
|
this.newProgress =
|
||||||
1 - this.timeToComplete / (parseInt('{{ charge.time }}') * 60)
|
1 - this.timeToComplete / (parseInt(this.charge.time) * 60)
|
||||||
},
|
},
|
||||||
loopRefresh: function () {
|
loopRefresh: function () {
|
||||||
// invoice only
|
// invoice only
|
||||||
@ -320,9 +339,50 @@
|
|||||||
if (this.charge.onchainaddress) this.checkAddressBalance()
|
if (this.charge.onchainaddress) this.checkAddressBalance()
|
||||||
}
|
}
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
},
|
||||||
|
initWs: async function () {
|
||||||
|
const {
|
||||||
|
bitcoin: {websocket}
|
||||||
|
} = mempoolJS({
|
||||||
|
hostname: 'mempool.space'
|
||||||
|
})
|
||||||
|
|
||||||
|
this.ws = new WebSocket('wss://mempool.space/api/v1/ws')
|
||||||
|
this.ws.addEventListener('open', x => {
|
||||||
|
console.log('### open ws', x)
|
||||||
|
})
|
||||||
|
this.ws.addEventListener('close', x => {
|
||||||
|
console.log('### close ws', x)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.ws.addEventListener('message', ({data}) => {
|
||||||
|
const res = JSON.parse(data.toString())
|
||||||
|
console.log('### socker mempool res', res)
|
||||||
|
if (res['address-transactions']) {
|
||||||
|
this.checkAddressBalance()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
loopPingWs: function () {
|
||||||
|
setInterval(() => {
|
||||||
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) this.initWs()
|
||||||
|
this.ws.send(JSON.stringify({action: 'ping'}))
|
||||||
|
}, 30 * 1000)
|
||||||
|
},
|
||||||
|
trackAddress: async function (address, retry = 0) {
|
||||||
|
try {
|
||||||
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) this.initWs()
|
||||||
|
console.log('### start to track: ', address)
|
||||||
|
this.ws.send(JSON.stringify({'track-address': address}))
|
||||||
|
} catch (error) {
|
||||||
|
await sleep(1000)
|
||||||
|
if (retry > 10) throw error
|
||||||
|
this.trackAddress(address, retry + 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created: function () {
|
created: function () {
|
||||||
|
console.log('### charge', this.charge)
|
||||||
if (this.charge.lnbitswallet) this.payInvoice()
|
if (this.charge.lnbitswallet) this.payInvoice()
|
||||||
else this.payOnchain()
|
else this.payOnchain()
|
||||||
|
|
||||||
@ -334,6 +394,10 @@
|
|||||||
this.loopRefresh()
|
this.loopRefresh()
|
||||||
}
|
}
|
||||||
this.startPaymentNotifier()
|
this.startPaymentNotifier()
|
||||||
|
if (this.charge.onchainaddress) {
|
||||||
|
this.loopPingWs()
|
||||||
|
this.trackAddress(this.charge.onchainaddress)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -34,5 +34,5 @@ async def display(request: Request, charge_id: str):
|
|||||||
inkey = wallet.inkey if wallet else None
|
inkey = wallet.inkey if wallet else None
|
||||||
return satspay_renderer().TemplateResponse(
|
return satspay_renderer().TemplateResponse(
|
||||||
"satspay/display.html",
|
"satspay/display.html",
|
||||||
{"request": request, "charge": charge.dict(), "wallet_inkey": inkey},
|
{"request": request, "charge_data": charge.dict(), "wallet_inkey": inkey},
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user