Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@

__all__ = [
"db",
"decoder_ext",
"decoder_static_files",
]
4 changes: 2 additions & 2 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"role": "Lead dev"
}
],
"version": "1.0.5",
"min_lnbits_version": "1.3.0",
"version": "1.1.0",
"min_lnbits_version": "1.5.0",
"license": "MIT"
}
120 changes: 120 additions & 0 deletions static/js/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
window.PageDecoder = {
template: '#page-decoder',
data() {
return {
input: '',
invoice: '',
decoderData: '',
lnurl: '',
lnurlData: '',
lnaddress: '',
lnaddressData: '',
invoiceData: ''
}
},
methods: {
blankallFields() {
this.invoice = ''
this.invoiceData = ''
this.lnurl = ''
this.lnurlData = ''
this.lnaddress = ''
this.lnaddressData = ''
},
sendFormData() {
let url = this.isValidLNaddress(this.input)
if (url != 'invalid') {
this.lnaddress = this.input
this.invoice = ''
this.invoiceData = ''
this.lnurl = ''
this.lnurlData = ''
this.decoderData = ''
this.getLNAddressData(url)
} else {
this.decoderFunction({data: this.input})
}
},
isValidLNaddress(address) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
let isValid = emailRegex.test(address)
if (isValid) {
const [name, domain] = address.split('@')
const url = `https://${domain}/.well-known/lnurlp/${name}`
return url
} else {
return 'invalid'
}
},
async getResponseData(url) {
try {
const response = await fetch(url)
if (!response.ok) {
throw new Error('Network response was not ok')
}
const data = await response.json()
return data
} catch (error) {
console.error('There was a problem with the fetch operation:', error)
}
},
async formatJSONToHTML(jsonData) {
let html = '<ul>'
for (const key in jsonData) {
html += `<li style="word-wrap: break-word;"><strong>${key}</strong> : `
if (typeof jsonData[key] === 'object') {
html += await this.formatJSONToHTML(jsonData[key])
} else {
html += jsonData[key]
}
html += '</li>'
}
html += '</ul>'
return html
},
async getLNURLData(data) {
let response = await this.getResponseData(data)
this.lnurlData = await this.formatJSONToHTML(response)
},
async getLNAddressData(data) {
let response = await this.getResponseData(data)
if (response === undefined) {
this.lnaddressData = await this.formatJSONToHTML({
error: 'Lightning address not valid'
})
return
}
this.lnaddressData = await this.formatJSONToHTML(response)
},
async getInvoiceData(data) {
this.invoiceData = await this.formatJSONToHTML(data)
},
async decoderFunction(data) {
LNbits.api
.request(
'POST',
'/api/v1/payments/decode',
this.g.user.wallets[0].inkey,
data
)
.then(async response => {
this.decoderData = response.data
this.blankallFields()
if (this.decoderData.hasOwnProperty('domain')) {
this.lnurl = this.input
let url = this.decoderData['domain']
this.getLNURLData(url)
} else {
this.invoice = this.input
this.getInvoiceData(response.data)
}
})
.catch(error => {
LNbits.utils.notifyApiError(error)
})
},
isObject(val) {
return val !== null && typeof val === 'object' && !Array.isArray(val)
}
}
}
90 changes: 90 additions & 0 deletions static/js/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<template id="page-decoder">
<div class="row q-col-gutter-md">
<div class="col-12 col-md-7 q-gutter-y-md">
<q-card flat>
<q-card-section>
<div class="row items-center no-wrap q-mb-sm">
<div class="col">
<strong>
Decode Lightning BOLT11, LNURL, and Lightning Address
</strong>
</div>
</div>
<div class="row items-center no-wrap q-mb-sm">
<div class="col">
<q-form @submit="sendFormData" class="q-gutter-md">
<q-input
filled
dense
clearable
placeholder="Enter Invoice, lnurl or ln address...."
v-model.trim="input"
label="input"
class="q-mb-md"
>
</q-input>
<q-btn unelevated color="primary" type="submit">Go</q-btn>
</q-form>
</div>
</div>
</q-card-section>
</q-card>
<q-card>
<q-card-section>
<div style="word-wrap: break-word" v-if="invoice">
<strong>Invoice:</strong> {{ invoice }}
<!-- invoice data only content -->
<div v-if="invoiceData.length > 0" v-html="invoiceData"></div>
</div>
<div style="word-wrap: break-word" v-if="lnurl">
<strong>LNURL:</strong> {{ lnurl }}
<!-- lnurl only content -->
<div v-if="lnurlData.length > 0" v-html="lnurlData"></div>
</div>
<div style="word-wrap: break-word" v-if="lnaddress">
<strong>Lightning Address:</strong> {{ lnaddress }}
<!-- ln address data only content -->
<div
v-if="Object.keys(lnaddressData).length > 0"
v-html="lnaddressData"
></div>
</div>
</q-card-section>
</q-card>
</div>

<div class="col-12 col-md-5 q-gutter-y-md">
<q-card>
<q-card-section>
<h6 class="text-subtitle1 q-my-none">
Decoder extension
</h6>
</q-card-section>
<q-card-section class="q-pa-none">
<q-separator></q-separator>
<q-list>
<q-card>
<q-card-section>
<p><b>Decoder Extension</b><br /></p>
<p>
Decoder is a simple BOLT11, LNURL, and Lightning Address decoder for
Lightning. Paste in your invoice or LNURL to decode. Useful for testing
and debugging while developing applications on the lightning network.
</p>
<small
>Created by
<a
class="text-secondary"
href="https://github.com/bitkarrot/decoder"
target="_blank"
>Bitkarrot</a
>
</small>
</q-card-section>
</q-card>
</q-list>
</q-card-section>
</q-card>
</div>
</div>
</template>
8 changes: 8 additions & 0 deletions static/routes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[
{
"path": "/decoder/",
"name": "PageDecoder",
"template": "/decoder/static/js/index.vue",
"component": "/decoder/static/js/index.js"
}
]
28 changes: 9 additions & 19 deletions views.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,12 @@
from fastapi import APIRouter, Depends, Request
from fastapi.responses import HTMLResponse
from lnbits.core.models import User
from lnbits.decorators import check_user_exists
from lnbits.helpers import template_renderer


def decoder_renderer():
return template_renderer(["decoder/templates"])

from fastapi import APIRouter, Depends
from lnbits.core.views.generic import index
from lnbits.decorators import check_account_id_exists

decoder_generic_router: APIRouter = APIRouter()


@decoder_generic_router.get("/", response_class=HTMLResponse)
async def index(
request: Request,
user: User = Depends(check_user_exists),
):
return decoder_renderer().TemplateResponse(
"decoder/index.html", {"request": request, "user": user.json()}
)
decoder_generic_router.add_api_route(
"/",
methods=["GET"],
endpoint=index,
dependencies=[Depends(check_account_id_exists)],
)
Loading