Compare commits

...
9 Commits
Author SHA1 Message Date
dni ⚡andGitHub e9d6160f4d chore: prepare for 0.12.9 (#2555) 2024-06-19 12:56:34 +02:00
Vlad StanandGitHub eacdd432b2 [feat] Extension details page (#2544)
* feat: add empty dialog

* feat: add `details_link` field for extension

* feat: show info icon if `details_link` present

* feat: add extension details endpoint

* feat: first details page

* feat: carousel working

* feat: full screen

* fix: layout

* fix: repo site

* fix: release icon

* fix: repo link

* feat: terms and conditions partial

* chore: fix typing

* fix: info icon layout

* chore: add try-catch

* feat: layout improvements

* feat: add video link

* fix: show terms and conditions

* chore: code format

* feat: add `details_link`

* fix: github release details

* feat: add close button

* chore: code clean-up

* chore: revert some changes

* feat: i18n

* chore: `make bundle`

* chore: make bundle

* feat: terms and conditions is a link now
2024-06-19 11:52:18 +01:00
Pavol RusnakandGitHub 76e8d72d0d LNBits -> LNbits typo (#2552)
* LNBits -> LNbits
2024-06-19 09:27:26 +03:00
dbacf7e8c1 "Failed to connect to https://ws:" crash (#2548)
* Update base.py

fixing bug in normalize_enpoints

* Update lnbits/wallets/base.py

Co-authored-by: Pavol Rusnak <pavol@rusnak.io>

---------

Co-authored-by: dni  <office@dnilabs.com>
Co-authored-by: Pavol Rusnak <pavol@rusnak.io>
2024-06-17 17:36:15 +02:00
dni ⚡andGitHub b6d99b09cf fix: npm packages with high severity issue (#2551)
updating `braces` npm package
2024-06-17 17:17:53 +02:00
5c21e7f9ed Update installation.md (#2549)
Minor rewording

---------

Co-authored-by: dni  <office@dnilabs.com>
2024-06-17 11:24:31 +02:00
14e9c7d9dc Fix typo of "LNbits" in list of funding sources. (#2546)
* Fix typo of "LNbits" in list of funding sources.


---------

Co-authored-by: Vlad Stan <stan.v.vlad@gmail.com>
2024-06-17 09:08:22 +02:00
blackcoffeexbtandGitHub b3368d89f4 Nice formatting of funding source titles in Server admin (#2543)
* Display friendly funding source titles in funding sources list

* Sort funding options select alphabetically

* Run make bundle
2024-06-10 23:37:09 +02:00
83b89851a5 fix: phoenixd wallet description field supports lnurlp (#2514)
* Fix for phoenixd and lnurlp nostr usage

- Support description, restricted to 128 characters
- Support descriptionHash

Co-authored-by: Pavol Rusnak <pavol@rusnak.io>
Co-authored-by: Vic <vic@example.com>
2024-05-29 13:47:10 +03:00
27 changed files with 353 additions and 54 deletions
+2 -2
View File
@@ -6,9 +6,9 @@ nav_order: 2
# Basic installation
You can choose between four package managers, `poetry` and `nix`
The following sections explain how to install LNbits using varions package managers: `poetry`, `nix`, `Docker` and `Fly.io`.
By default, LNbits will use SQLite as its database. You can also use PostgreSQL which is recommended for applications with a high load (see guide below).
Note that by default LNbits uses SQLite as its database, which is simple and effective but you can configure it to use PostgreSQL instead which is also described in a section below.
## Option 1 (recommended): poetry
+218 -7
View File
@@ -87,10 +87,17 @@
<div class="col-9 q-pl-sm">
<q-badge
v-if="hasNewVersion(extension)"
@click="showExtensionDetails(extension.id, extension.latestRelease?.details_link)"
color="green"
class="float-right"
:class="extension.latestRelease?.details_link ? 'cursor-pointer': ''"
>
<small v-text="$t('new_version')"></small>
<q-icon
v-if="extension.latestRelease?.details_link"
name="info"
size="xs"
></q-icon>
<small v-text="$t('new_version')" class="q-ma-xs"></small>
<q-tooltip
><span v-text="extension.latestRelease.version"></span
></q-tooltip>
@@ -227,14 +234,27 @@
<div class="col-2">
<div
v-if="extension.isInstalled && extension.installedRelease"
v-if="(extension.isInstalled && extension.installedRelease) || extension.details_link"
class="float-right"
>
<q-badge>
<span v-text="extension.installedRelease.version"></span>
<q-tooltip>
<span v-text="$t('extension_installed_version')"></span>
</q-tooltip>
<q-badge
@click="showExtensionDetails(extension.id, extension.details_link)"
:class="extension.details_link? 'cursor-pointer' : ''"
>
<q-icon
v-if="extension.details_link"
name="info"
size="xs"
></q-icon>
<div v-if="extension.installedRelease" class="q-ma-xs">
<span
v-text="extension.installedRelease.version"
class="q-mt-lg"
></span>
<q-tooltip>
<span v-text="$t('extension_installed_version')"></span>
</q-tooltip>
</div>
</q-badge>
</div>
</div>
@@ -754,23 +774,186 @@
</q-card-section>
</q-card>
</q-dialog>
<q-dialog v-model="showExtensionDetailsDialog">
<q-card
v-if="selectedExtensionDetails"
class="q-pa-lg"
style="width: 800px; max-width: 80vw"
>
<q-card-section>
<div class="row">
<div class="col-2 gt-md">
<q-img
:src="selectedExtensionDetails.icon"
style="width: 100px"
type="image"
></q-img>
</div>
<div class="col-7 q-pl-md">
<h3 class="q-my-sm" v-text="selectedExtensionDetails.name"></h3>
<h6
class="q-my-sm"
v-text="selectedExtensionDetails.short_description"
></h6>
</div>
<div class="col-3">
<q-btn
v-close-popup
flat
color="grey"
class="float-right q-ml-lg"
v-text="$t('close')"
></q-btn>
</div>
</div>
<div v-if="selectedExtensionDetails.images?.length" class="row q-my-lg">
<div class="col q-pr-md">
<q-carousel
swipeable
animated
v-model="slide"
:fullscreen.sync="fullscreen"
thumbnails
infinite
:autoplay="autoplay"
arrows
transition-prev="slide-right"
transition-next="slide-left"
@mouseenter="autoplay = false"
@mouseleave="autoplay = true"
height="300px"
>
<template v-slot:control>
<q-carousel-control position="bottom-right" :offset="[18, 18]">
<q-btn
push
round
dense
color="white"
text-color="primary"
:icon="fullscreen ? 'fullscreen_exit' : 'fullscreen'"
@click="fullscreen = !fullscreen"
></q-btn>
</q-carousel-control>
</template>
<q-carousel-slide
v-for="(image, i) of selectedExtensionDetails.images"
:img-src="image.uri"
:key="i"
:name="i"
>
<q-video
v-if="image.link"
class="absolute-full"
:src="image.link"
/>
</q-carousel-slide>
</q-carousel>
</div>
</div>
<div class="row">
<div class="col-8 q-pr-sm">
<div v-html="selectedExtensionDetails.description_md"></div>
</div>
<div class="col-4 q-pl-sm" style="border-left: 1px solid grey">
<div class="">
<q-btn
size="xs"
color="primary"
label="Terms and conditions"
type="a"
:href="selectedExtensionDetails.terms_and_conditions_md"
target="_blank"
rel="noopener noreferrer"
></q-btn>
</div>
<div class="q-mt-md">
<b>
<span v-text="$t('contributors')"></span>
</b>
<small>
<div
v-for="contributor of selectedExtensionDetails.contributors"
>
<a
:href="contributor.uri"
target="_blank"
rel="noopener noreferrer"
style="color: var(--q-primary); text-decoration: none"
>
<span
v-text="(contributor.name || contributor) + ' - ' + (contributor.role || 'dev')"
></span>
</a>
</div>
</small>
</div>
<div class="q-pt-lg">
<div>
<b>
<span v-text="$t('license')"></span>
</b>
<q-badge
color="primary"
v-text="selectedExtensionDetails.license"
></q-badge>
</div>
<br />
<div>
<q-rating
v-model="maxStars"
disable
size="1.5em"
:max="5"
color="primary"
><q-tooltip>
<span
v-text="$t('extension_rating_soon')"
></span> </q-tooltip
></q-rating>
<q-btn
size="xs"
color="primary"
:label="$t('repository')"
type="a"
:href="selectedExtensionDetails.repo"
target="_blank"
rel="noopener noreferrer"
></q-btn>
</div>
</div>
</div>
</div>
</q-card-section>
</q-card>
</q-dialog>
</div>
{% endblock %} {% block scripts %} {{ window_vars(user) }}
<script>
new Vue({
el: '#vue',
data: function () {
return {
slide: 0,
fullscreen: false,
autoplay: true,
searchTerm: '',
tab: 'all',
manageExtensionTab: 'releases',
filteredExtensions: null,
showUninstallDialog: false,
showManageExtensionDialog: false,
showExtensionDetailsDialog: false,
showDropDbDialog: false,
showPayToEnableDialog: false,
dropDbExtensionId: '',
selectedExtension: null,
selectedImage: null,
selectedExtensionDetails: null,
selectedExtensionRepos: null,
selectedRelease: null,
uninstallAndDropDb: false,
@@ -812,6 +995,11 @@
)
.filter(e => (tab === 'featured' ? e.isFeatured : true))
.filter(extensionNameContains(term))
.map(e => ({
...e,
details_link:
e.installedRelease?.details_link || e.latestRelease?.details_link
}))
this.tab = tab
},
@@ -1069,6 +1257,29 @@
}
},
showExtensionDetails: async function (extId, detailsLink) {
if (!detailsLink) {
return
}
this.selectedExtensionDetails = null
this.showExtensionDetailsDialog = true
this.slide = 0
this.fullscreen = false
try {
const {data} = await LNbits.api.request(
'GET',
`/api/v1/extension/${extId}/details?details_link=${detailsLink}`,
this.g.user.wallets[0].inkey
)
this.selectedExtensionDetails = data
this.selectedExtensionDetails.description_md =
LNbits.utils.convertMarkdown(data.description_md)
} catch (error) {
console.warn(error)
}
},
async payAndInstall(release) {
try {
this.selectedExtension.inProgress = true
+30
View File
@@ -37,6 +37,7 @@ from lnbits.extension_manager import (
ReleasePaymentInfo,
UserExtensionInfo,
fetch_github_release_config,
fetch_release_details,
fetch_release_payment_info,
get_valid_extensions,
)
@@ -128,6 +129,35 @@ async def api_install_extension(
) from exc
@extension_router.get("/{ext_id}/details", dependencies=[Depends(check_user_exists)])
async def api_extension_details(
ext_id: str,
details_link: str,
):
try:
all_releases = await InstallableExtension.get_extension_releases(ext_id)
release = next(
(r for r in all_releases if r.details_link == details_link), None
)
assert release, "Details not found for release"
release_details = await fetch_release_details(details_link)
assert release_details, "Cannot fetch details for release"
release_details["icon"] = release.icon
release_details["repo"] = release.repo
return release_details
except AssertionError as exc:
raise HTTPException(HTTPStatus.BAD_REQUEST, str(exc)) from exc
except Exception as exc:
logger.warning(exc)
raise HTTPException(
HTTPStatus.INTERNAL_SERVER_ERROR,
f"Failed to get details for extension {ext_id}.",
) from exc
@extension_router.put("/{ext_id}/sell")
async def api_update_pay_to_enable(
ext_id: str,
+34 -3
View File
@@ -32,6 +32,7 @@ class ExplicitRelease(BaseModel):
warning: Optional[str]
info_notification: Optional[str]
critical_notification: Optional[str]
details_link: Optional[str]
pay_link: Optional[str]
def is_version_compatible(self):
@@ -58,6 +59,9 @@ class GitHubRepoRelease(BaseModel):
zipball_url: str
html_url: str
def details_link(self, source_repo: str) -> str:
return f"https://raw.githubusercontent.com/{source_repo}/{self.tag_name}/config.json"
class GitHubRepo(BaseModel):
stargazers_count: str
@@ -210,6 +214,24 @@ async def fetch_release_payment_info(
return None
async def fetch_release_details(details_link: str) -> Optional[dict]:
try:
async with httpx.AsyncClient() as client:
resp = await client.get(details_link)
resp.raise_for_status()
data = resp.json()
if "description_md" in data:
resp = await client.get(data["description_md"])
if not resp.is_error:
data["description_md"] = resp.text
return data
except Exception as e:
logger.warning(e)
return None
def icon_to_github_url(source_repo: str, path: Optional[str]) -> str:
if not path:
return ""
@@ -315,6 +337,7 @@ class ExtensionRelease(BaseModel):
warning: Optional[str] = None
repo: Optional[str] = None
icon: Optional[str] = None
details_link: Optional[str] = None
pay_link: Optional[str] = None
cost_sats: Optional[int] = None
@@ -347,6 +370,7 @@ class ExtensionRelease(BaseModel):
archive=r.zipball_url,
source_repo=source_repo,
is_github_release=True,
details_link=r.details_link(source_repo),
repo=f"https://github.com/{source_repo}",
html_url=r.html_url,
)
@@ -366,6 +390,7 @@ class ExtensionRelease(BaseModel):
is_version_compatible=e.is_version_compatible(),
warning=e.warning,
html_url=e.html_url,
details_link=e.details_link,
pay_link=e.pay_link,
repo=e.repo,
icon=e.icon,
@@ -613,18 +638,18 @@ class InstallableExtension(BaseModel):
repo, latest_release, config = await fetch_github_repo_info(
github_release.organisation, github_release.repository
)
source_repo = f"{github_release.organisation}/{github_release.repository}"
return InstallableExtension(
id=github_release.id,
name=config.name,
short_description=config.short_description,
stars=int(repo.stargazers_count),
icon=icon_to_github_url(
f"{github_release.organisation}/{github_release.repository}",
source_repo,
config.tile,
),
latest_release=ExtensionRelease.from_github_release(
repo.html_url, latest_release
source_repo, latest_release
),
)
except Exception as e:
@@ -740,6 +765,12 @@ class CreateExtension(BaseModel):
payment_hash: Optional[str] = None
class ExtensionDetailsRequest(BaseModel):
ext_id: str
source_repo: str
version: str
def get_valid_extensions(include_deactivated: Optional[bool] = True) -> List[Extension]:
valid_extensions = [
extension for extension in ExtensionManager().extensions if extension.is_valid
+1 -1
View File
@@ -16,7 +16,7 @@ from lnbits.settings import set_cli_settings, settings
}
)
@click.option("--port", default=settings.port, help="Port to listen on")
@click.option("--host", default=settings.host, help="Host to run LNBits on")
@click.option("--host", default=settings.host, help="Host to run LNbits on")
@click.option(
"--forwarded-allow-ips",
default=settings.forwarded_allow_ips,
+9 -9
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -169,7 +169,7 @@ window.localisation.br = {
'Se ativado, mudará sua fonte de fundos para VoidWallet automaticamente se o LNbits enviar um sinal de desativação. Você precisará ativar manualmente após uma atualização.',
killswitch_interval: 'Intervalo do Killswitch',
killswitch_interval_desc:
'Com que frequência a tarefa de fundo deve verificar o sinal de desativação do LNBits proveniente da fonte de status (em minutos).',
'Com que frequência a tarefa de fundo deve verificar o sinal de desativação do LNbits proveniente da fonte de status (em minutos).',
enable_watchdog: 'Ativar Watchdog',
enable_watchdog_desc:
'Se ativado, ele mudará automaticamente sua fonte de financiamento para VoidWallet se o seu saldo for inferior ao saldo do LNbits. Você precisará ativar manualmente após uma atualização.',
+1 -1
View File
@@ -159,7 +159,7 @@ window.localisation.cn = {
'如果启用,当LNbits发送终止信号时,系统将自动将您的资金来源更改为VoidWallet。更新后,您将需要手动启用。',
killswitch_interval: 'Killswitch 间隔',
killswitch_interval_desc:
'后台任务应该多久检查一次来自状态源的LNBits断路信号(以分钟为单位)。',
'后台任务应该多久检查一次来自状态源的LNbits断路信号(以分钟为单位)。',
enable_watchdog: '启用看门狗',
enable_watchdog_desc:
'如果启用,当您的余额低于LNbits余额时,系统将自动将您的资金来源更改为VoidWallet。更新后您将需要手动启用。',
+1 -1
View File
@@ -166,7 +166,7 @@ window.localisation.cs = {
'Pokud je povoleno, automaticky změní zdroj financování na VoidWallet pokud LNbits odešle signál killswitch. Po aktualizaci budete muset povolit ručně.',
killswitch_interval: 'Interval Killswitch',
killswitch_interval_desc:
'Jak často by měl úkol na pozadí kontrolovat signál killswitch od LNBits ze zdroje stavu (v minutách).',
'Jak často by měl úkol na pozadí kontrolovat signál killswitch od LNbits ze zdroje stavu (v minutách).',
enable_watchdog: 'Povolit Watchdog',
enable_watchdog_desc:
'Pokud je povoleno, automaticky změní zdroj financování na VoidWallet pokud je váš zůstatek nižší než zůstatek LNbits. Po aktualizaci budete muset povolit ručně.',
+1 -1
View File
@@ -171,7 +171,7 @@ window.localisation.de = {
'Falls aktiviert, wird Ihre Zahlungsquelle automatisch auf VoidWallet umgestellt, wenn LNbits ein Killswitch-Signal sendet. Nach einem Update müssen Sie dies manuell wieder aktivieren.',
killswitch_interval: 'Intervall für den Notausschalter',
killswitch_interval_desc:
'Wie oft die Hintergrundaufgabe nach dem LNBits-Killswitch-Signal aus der Statusquelle suchen soll (in Minuten).',
'Wie oft die Hintergrundaufgabe nach dem LNbits-Killswitch-Signal aus der Statusquelle suchen soll (in Minuten).',
enable_watchdog: 'Aktiviere Watchdog',
enable_watchdog_desc:
'Wenn aktiviert, wird Ihre Zahlungsquelle automatisch auf VoidWallet umgestellt, wenn Ihr Guthaben niedriger als das LNbits-Guthaben ist. Nach einem Update müssen Sie dies manuell aktivieren.',
+4 -2
View File
@@ -165,7 +165,7 @@ window.localisation.en = {
'If enabled it will change your funding source to VoidWallet automatically if LNbits sends out a killswitch signal. You will need to enable manually after an update.',
killswitch_interval: 'Killswitch Interval',
killswitch_interval_desc:
'How often the background task should check for the LNBits killswitch signal from the status source (in minutes).',
'How often the background task should check for the LNbits killswitch signal from the status source (in minutes).',
enable_watchdog: 'Enable Watchdog',
enable_watchdog_desc:
'If enabled it will change your funding source to VoidWallet automatically if your balance is lower than the LNbits balance. You will need to enable manually after an update.',
@@ -258,5 +258,7 @@ window.localisation.en = {
sell_info:
'The %{name} extension requires a payment of minimum %{amount} sats to enable.',
hide_empty_wallets: 'Hide empty wallets',
recheck: 'Recheck'
recheck: 'Recheck',
contributors: 'Contributors',
license: 'License'
}
+1 -1
View File
@@ -169,7 +169,7 @@ window.localisation.es = {
'Si está activado, cambiará automáticamente su fuente de financiamiento a VoidWallet si LNbits envía una señal de parada de emergencia. Necesitará activarlo manualmente después de una actualización.',
killswitch_interval: 'Intervalo de Killswitch',
killswitch_interval_desc:
'Con qué frecuencia la tarea en segundo plano debe verificar la señal de interruptor de emergencia de LNBits desde la fuente de estado (en minutos).',
'Con qué frecuencia la tarea en segundo plano debe verificar la señal de interruptor de emergencia de LNbits desde la fuente de estado (en minutos).',
enable_watchdog: 'Activar Watchdog',
enable_watchdog_desc:
'Si está activado, cambiará automáticamente su fuente de financiamiento a VoidWallet si su saldo es inferior al saldo de LNbits. Tendrá que activarlo manualmente después de una actualización.',
+1 -1
View File
@@ -66,7 +66,7 @@ window.localisation.fi = {
service_fee_max:
'Palvelumaksu: %{amount} % tapahtumasta (enintään %{max} sat)',
service_fee_tooltip:
'LNBits palvelimen ylläpitäjä veloittaa lähtevästä maksusta palvelumaksun.',
'LNbits palvelimen ylläpitäjä veloittaa lähtevästä maksusta palvelumaksun.',
toggle_darkmode: 'Tumma näkymä',
payment_reactions: 'Maksureaktiot',
view_swagger_docs: 'Näytä LNbits Swagger API-dokumentit',
+1 -1
View File
@@ -173,7 +173,7 @@ window.localisation.fr = {
'Si activé, il changera automatiquement votre source de financement en VoidWallet si LNbits envoie un signal de coupure. Vous devrez activer manuellement après une mise à jour.',
killswitch_interval: 'Intervalle du Killswitch',
killswitch_interval_desc:
"À quelle fréquence la tâche de fond doit-elle vérifier le signal d'arrêt d'urgence LNBits provenant de la source de statut (en minutes).",
"À quelle fréquence la tâche de fond doit-elle vérifier le signal d'arrêt d'urgence LNbits provenant de la source de statut (en minutes).",
enable_watchdog: 'Activer le Watchdog',
enable_watchdog_desc:
'Si elle est activée, elle changera automatiquement votre source de financement en VoidWallet si votre solde est inférieur au solde LNbits. Vous devrez activer manuellement après une mise à jour.',
+1 -1
View File
@@ -169,7 +169,7 @@ window.localisation.it = {
'Se attivato, cambierà automaticamente la tua fonte di finanziamento in VoidWallet se LNbits invia un segnale di killswitch. Dovrai attivare manualmente dopo un aggiornamento.',
killswitch_interval: 'Intervallo Killswitch',
killswitch_interval_desc:
'Quanto spesso il compito in background dovrebbe controllare il segnale di killswitch LNBits dalla fonte di stato (in minuti).',
'Quanto spesso il compito in background dovrebbe controllare il segnale di killswitch LNbits dalla fonte di stato (in minuti).',
enable_watchdog: 'Attiva Watchdog',
enable_watchdog_desc:
'Se abilitato, cambierà automaticamente la tua fonte di finanziamento in VoidWallet se il tuo saldo è inferiore al saldo LNbits. Dovrai abilitarlo manualmente dopo un aggiornamento.',
+1 -1
View File
@@ -166,7 +166,7 @@ window.localisation.jp = {
'有効にすると、LNbitsからキルスイッチ信号が送信された場合に自動的に資金源をVoidWalletに切り替えます。更新後には手動で有効にする必要があります。',
killswitch_interval: 'キルスイッチ間隔',
killswitch_interval_desc:
'バックグラウンドタスクがステータスソースからLNBitsキルスイッチ信号を確認する頻度(分単位)。',
'バックグラウンドタスクがステータスソースからLNbitsキルスイッチ信号を確認する頻度(分単位)。',
enable_watchdog: 'ウォッチドッグを有効にする',
enable_watchdog_desc:
'有効にすると、残高がLNbitsの残高より少ない場合に、資金源を自動的にVoidWalletに変更します。アップデート後は手動で有効にする必要があります。',
+2 -2
View File
@@ -40,7 +40,7 @@ window.localisation.kr = {
'성공적으로 가상 자금을 생성했습니다 (%{amount} sats). 지급은 자금 원천의 실제 자금에 따라 달라집니다.',
paste_invoice_label: '인보이스, 결제 요청, 혹은 lnurl 코드를 붙여넣으세요 *',
lnbits_description:
'설정이 쉽고 가벼운 LNBits는 어떤 라이트닝 네트워크의 예산 자원 위에서든 돌아갈 수 있습니다, 그리고 다른 LNBits 지갑들입니다. 스스로 사용하기 위해, 또는 다른 사람들에게 수탁형 솔루션을 제공하기 위해 LNBits를 운영할 수 있습니다. 각 지갑들은 자신만의 API key를 가지며, 생성 가능한 지갑의 수에는 제한이 없습니다. 자금을 분할할 수 있는 기능으로 인해, LNBits는 자금 운영 도구로써뿐만 아니라 개발 도구로써도 유용합니다. 확장 기능들은 LNBits에 여러분들이 라이트닝 네트워크의 다양한 최신 기술들을 수행해볼 수 있게 하는 추가 기능을 제공합니다. LNBits 개발진들은 확장 기능들의 개발 또한 가능한 쉽게 만들었으며, 무료 오픈 소스 프로젝트답게 사람들이 자신만의 확장 기능들을 개발하고 제출하기를 응원합니다.',
'설정이 쉽고 가벼운 LNbits는 어떤 라이트닝 네트워크의 예산 자원 위에서든 돌아갈 수 있습니다, 그리고 다른 LNbits 지갑들입니다. 스스로 사용하기 위해, 또는 다른 사람들에게 수탁형 솔루션을 제공하기 위해 LNbits를 운영할 수 있습니다. 각 지갑들은 자신만의 API key를 가지며, 생성 가능한 지갑의 수에는 제한이 없습니다. 자금을 분할할 수 있는 기능으로 인해, LNbits는 자금 운영 도구로써뿐만 아니라 개발 도구로써도 유용합니다. 확장 기능들은 LNbits에 여러분들이 라이트닝 네트워크의 다양한 최신 기술들을 수행해볼 수 있게 하는 추가 기능을 제공합니다. LNbits 개발진들은 확장 기능들의 개발 또한 가능한 쉽게 만들었으며, 무료 오픈 소스 프로젝트답게 사람들이 자신만의 확장 기능들을 개발하고 제출하기를 응원합니다.',
export_to_phone: 'QR 코드를 이용해 모바일 기기로 내보내기',
export_to_phone_desc:
'이 QR 코드는 선택된 지갑의 최대 접근 권한을 가진 전체 URL을 담고 있습니다. 스캔 후, 모바일 기기에서 지갑을 열 수 있습니다.',
@@ -62,7 +62,7 @@ window.localisation.kr = {
service_fee: '서비스 수수료: 거래액의 %{amount} %',
service_fee_max: '서비스 수수료: 거래액의 %{amount} % (최대 %{max} sats)',
service_fee_tooltip:
'지불 결제 시마다 LNBits 서버 관리자에게 납부되는 서비스 수수료',
'지불 결제 시마다 LNbits 서버 관리자에게 납부되는 서비스 수수료',
toggle_darkmode: '다크 모드 전환',
payment_reactions: '결제 반응',
view_swagger_docs: 'LNbits Swagger API 문서를 봅니다',
+1 -1
View File
@@ -169,7 +169,7 @@ window.localisation.nl = {
'Indien ingeschakeld, zal het uw financieringsbron automatisch wijzigen naar VoidWallet als LNbits een killswitch-signaal verzendt. U zult het na een update handmatig moeten inschakelen.',
killswitch_interval: 'Uitschakelschakelaar-interval',
killswitch_interval_desc:
'Hoe vaak de achtergrondtaak moet controleren op het LNBits killswitch signaal van de statusbron (in minuten).',
'Hoe vaak de achtergrondtaak moet controleren op het LNbits killswitch signaal van de statusbron (in minuten).',
enable_watchdog: 'Inschakelen Watchdog',
enable_watchdog_desc:
'Indien ingeschakeld, wordt uw betaalbron automatisch gewijzigd naar VoidWallet als uw saldo lager is dan het saldo van LNbits. U zult dit na een update handmatig moeten inschakelen.',
+1 -1
View File
@@ -168,7 +168,7 @@ window.localisation.pi = {
"If enabled it'll be changin' yer fundin' source to VoidWallet automatically if LNbits sends out a killswitch signal, ye will. Ye'll be needin' t' enable manually after an update, arr.",
killswitch_interval: 'Killswitch Interval',
killswitch_interval_desc:
"How oft th' background task should be checkin' fer th' LNBits killswitch signal from th' status source (in minutes).",
"How oft th' background task should be checkin' fer th' LNbits killswitch signal from th' status source (in minutes).",
enable_watchdog: 'Enable Seadog',
enable_watchdog_desc:
"If enabled, it will swap yer treasure source t' VoidWallet on its own if yer balance be lower than th' LNbits balance. Ye'll need t' enable by hand after an update.",
+1 -1
View File
@@ -166,7 +166,7 @@ window.localisation.pl = {
'Jeśli zostanie włączone, automatycznie zmieni źródło finansowania na VoidWallet, jeśli LNbits wyśle sygnał wyłączający. Po aktualizacji będziesz musiał włączyć to ręcznie.',
killswitch_interval: 'Interwał wyłącznika awaryjnego',
killswitch_interval_desc:
'Jak często zadanie w tle powinno sprawdzać sygnał wyłącznika awaryjnego LNBits ze źródła statusu (w minutach).',
'Jak często zadanie w tle powinno sprawdzać sygnał wyłącznika awaryjnego LNbits ze źródła statusu (w minutach).',
enable_watchdog: 'Włącz Watchdog',
enable_watchdog_desc:
'Jeśli zostanie włączone, automatycznie zmieni źródło finansowania na VoidWallet, jeśli saldo jest niższe niż saldo LNbits. Po aktualizacji trzeba będzie włączyć ręcznie.',
+1 -1
View File
@@ -168,7 +168,7 @@ window.localisation.pt = {
'Se ativado, ele mudará sua fonte de financiamento para VoidWallet automaticamente se o LNbits enviar um sinal de desativação. Você precisará ativar manualmente após uma atualização.',
killswitch_interval: 'Intervalo do Killswitch',
killswitch_interval_desc:
'Com que frequência a tarefa de fundo deve verificar o sinal de desativação do LNBits proveniente da fonte de status (em minutos).',
'Com que frequência a tarefa de fundo deve verificar o sinal de desativação do LNbits proveniente da fonte de status (em minutos).',
enable_watchdog: 'Ativar Watchdog',
enable_watchdog_desc:
'Se ativado, mudará automaticamente a sua fonte de financiamento para VoidWallet caso o seu saldo seja inferior ao saldo LNbits. Você precisará ativar manualmente após uma atualização.',
+1 -1
View File
@@ -166,7 +166,7 @@ window.localisation.we = {
'Os bydd yn galluogi, bydd yn newid eich ffynhonnell arian i VoidWallet yn awtomatig os bydd LNbits yn anfon arwydd killswitch. Bydd angen i chi alluogi â llaw ar ôl diweddariad.',
killswitch_interval: 'Amlder Cyllell Dorri',
killswitch_interval_desc:
"Pa mor aml y dylai'r dasg gefndir wirio am signal killswitch LNBits o'r ffynhonnell statws (mewn munudau).",
"Pa mor aml y dylai'r dasg gefndir wirio am signal killswitch LNbits o'r ffynhonnell statws (mewn munudau).",
enable_watchdog: 'Galluogi Watchdog',
enable_watchdog_desc:
'Os bydd yn cael ei alluogi bydd yn newid eich ffynhonnell ariannu i VoidWallet yn awtomatig os bydd eich balans yn is na balans LNbits. Bydd angen i chi alluogi â llaw ar ôl diweddariad.',
@@ -1,6 +1,14 @@
Vue.component('lnbits-funding-sources', {
mixins: [windowMixin],
props: ['form-data', 'allowed-funding-sources'],
methods: {
getFundingSourceLabel(item) {
const fundingSource = this.rawFundingSources.find(
fundingSource => fundingSource[0] === item
)
return fundingSource ? fundingSource[1] : item
}
},
computed: {
fundingSources() {
let tmp = []
@@ -14,6 +22,9 @@ Vue.component('lnbits-funding-sources', {
tmp.push([key, tmpObj])
}
return new Map(tmp)
},
sortedAllowedFundingSources() {
return this.allowedFundingSources.sort()
}
},
data() {
@@ -93,7 +104,7 @@ Vue.component('lnbits-funding-sources', {
],
[
'LNbitsWallet',
'LNBits',
'LNbits',
{
lnbits_endpoint: 'Endpoint',
lnbits_key: 'Admin Key'
@@ -159,7 +170,8 @@ Vue.component('lnbits-funding-sources', {
filled
v-model="formData.lnbits_backend_wallet_class"
hint="Select the active funding wallet"
:options="allowedFundingSources"
:options="sortedAllowedFundingSources"
:option-label="(item) => getFundingSourceLabel(item)"
></q-select>
</div>
</div>
+2
View File
@@ -137,6 +137,8 @@ class Wallet(ABC):
def normalize_endpoint(self, endpoint: str, add_proto=True) -> str:
endpoint = endpoint[:-1] if endpoint.endswith("/") else endpoint
if add_proto:
if endpoint.startswith("ws://") or endpoint.startswith("wss://"):
return endpoint
endpoint = (
f"https://{endpoint}" if not endpoint.startswith("http") else endpoint
)
+15 -4
View File
@@ -1,5 +1,6 @@
import asyncio
import base64
import hashlib
import json
import urllib.parse
from typing import AsyncGenerator, Dict, Optional
@@ -17,7 +18,6 @@ from .base import (
PaymentStatus,
PaymentSuccessStatus,
StatusResponse,
UnsupportedError,
Wallet,
)
@@ -87,17 +87,28 @@ class PhoenixdWallet(Wallet):
unhashed_description: Optional[bytes] = None,
**kwargs,
) -> InvoiceResponse:
if description_hash or unhashed_description:
raise UnsupportedError("description_hash")
try:
msats_amount = amount
data: Dict = {
"amountSat": f"{msats_amount}",
"description": memo,
"externalId": "",
}
# Either 'description' (string) or 'descriptionHash' must be supplied
# PhoenixD description limited to 128 characters
if description_hash:
data["descriptionHash"] = description_hash.hex()
else:
desc = memo
if desc is None and unhashed_description:
desc = unhashed_description.decode()
desc = desc or ""
if len(desc) > 128:
data["descriptionHash"] = hashlib.sha256(desc.encode()).hexdigest()
else:
data["description"] = desc
r = await self.client.post(
"/createinvoice",
data=data,
+7 -7
View File
@@ -168,12 +168,12 @@
}
},
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"dependencies": {
"fill-range": "^7.0.1"
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
@@ -434,9 +434,9 @@
}
},
"node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
+1 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "lnbits"
version = "0.12.8"
version = "0.12.9"
description = "LNbits, free and open-source Lightning wallet and accounts system."
authors = ["Alan Bits <alan@lnbits.com>"]
readme = "README.md"