Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07428ecf94 | ||
|
|
867e3d06f6 | ||
|
|
4b4b6d0bcd | ||
|
|
07b1521dad | ||
|
|
7a2ddd9826 | ||
|
|
0eb4b477b7 | ||
|
|
06a0ba58ce | ||
|
|
5399b36027 |
+5
-4
@@ -324,7 +324,8 @@ class AssetSettings(LNbitsSettings):
|
|||||||
"heif",
|
"heif",
|
||||||
"heics",
|
"heics",
|
||||||
"text/plain",
|
"text/plain",
|
||||||
"text/json" "text/xml",
|
"text/json",
|
||||||
|
"text/xml",
|
||||||
"application/json",
|
"application/json",
|
||||||
"application/pdf",
|
"application/pdf",
|
||||||
]
|
]
|
||||||
@@ -588,6 +589,8 @@ class ZBDFundingSource(LNbitsSettings):
|
|||||||
class PhoenixdFundingSource(LNbitsSettings):
|
class PhoenixdFundingSource(LNbitsSettings):
|
||||||
phoenixd_api_endpoint: str | None = Field(default="http://localhost:9740/")
|
phoenixd_api_endpoint: str | None = Field(default="http://localhost:9740/")
|
||||||
phoenixd_api_password: str | None = Field(default=None)
|
phoenixd_api_password: str | None = Field(default=None)
|
||||||
|
phoenixd_data_dir: str | None = Field(default=None)
|
||||||
|
phoenixd_mnemonic: str | None = Field(default=None)
|
||||||
|
|
||||||
|
|
||||||
class AlbyFundingSource(LNbitsSettings):
|
class AlbyFundingSource(LNbitsSettings):
|
||||||
@@ -1007,9 +1010,7 @@ class EnvSettings(LNbitsSettings):
|
|||||||
debug_database: bool = Field(default=False)
|
debug_database: bool = Field(default=False)
|
||||||
bundle_assets: bool = Field(default=True)
|
bundle_assets: bool = Field(default=True)
|
||||||
# When enabled, auth cookies require HTTPS and SSO will reject insecure HTTP.
|
# When enabled, auth cookies require HTTPS and SSO will reject insecure HTTP.
|
||||||
# Keep disabled by default so local HTTP installs continue to work unless
|
auth_https_only: bool = Field(default=True)
|
||||||
# operators explicitly opt into HTTPS-only auth cookies.
|
|
||||||
auth_https_only: bool = Field(default=False)
|
|
||||||
host: str = Field(default="127.0.0.1")
|
host: str = Field(default="127.0.0.1")
|
||||||
port: int = Field(default=5000, gt=0)
|
port: int = Field(default=5000, gt=0)
|
||||||
forwarded_allow_ips: str = Field(default="*")
|
forwarded_allow_ips: str = Field(default="*")
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+11
-11
File diff suppressed because one or more lines are too long
@@ -275,6 +275,8 @@ window.localisation.en = {
|
|||||||
requires_server_restart:
|
requires_server_restart:
|
||||||
'Changing these settings requires a server restart to take effect.',
|
'Changing these settings requires a server restart to take effect.',
|
||||||
funding_source_info: 'Select the active funding wallet',
|
funding_source_info: 'Select the active funding wallet',
|
||||||
|
phoenixd_warning:
|
||||||
|
"Phoenixd mnemonic is only available if phoenixd data-dir is specified and is readable by LNbits. It's not indicative of phoenixd not running. It just means LNbits cannot access the mnemonic to display it here.",
|
||||||
latest_update: 'You are on the latest version {version}.',
|
latest_update: 'You are on the latest version {version}.',
|
||||||
notifications: 'Notifications',
|
notifications: 'Notifications',
|
||||||
notifications_configure: 'Configure Notifications',
|
notifications_configure: 'Configure Notifications',
|
||||||
|
|||||||
@@ -202,7 +202,18 @@ window.app.component('lnbits-admin-funding-sources', {
|
|||||||
'Phoenixd',
|
'Phoenixd',
|
||||||
{
|
{
|
||||||
phoenixd_api_endpoint: 'Endpoint',
|
phoenixd_api_endpoint: 'Endpoint',
|
||||||
phoenixd_api_password: 'Key'
|
phoenixd_api_password: 'Key',
|
||||||
|
phoenixd_data_dir: {
|
||||||
|
label: 'Data Directory',
|
||||||
|
hint: 'Directory where phoenixd stores its data, including the seed phrase.'
|
||||||
|
},
|
||||||
|
phoenixd_mnemonic: {
|
||||||
|
label: 'Phoenixd Seed Phrase',
|
||||||
|
hint: 'Only available if phoenixd data-dir is specified',
|
||||||
|
readonly: true,
|
||||||
|
copy: true,
|
||||||
|
qrcode: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -41,5 +41,37 @@ window.app.component('lnbits-admin-site-customisation', {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {}
|
methods: {
|
||||||
|
onBackgroundImageInput(e) {
|
||||||
|
const file = e.target.files[0]
|
||||||
|
if (file) {
|
||||||
|
this.uploadBackgroundImage(file)
|
||||||
|
}
|
||||||
|
e.target.value = null
|
||||||
|
},
|
||||||
|
async uploadBackgroundImage(file) {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', file)
|
||||||
|
try {
|
||||||
|
const {data} = await LNbits.api.request(
|
||||||
|
'POST',
|
||||||
|
'/api/v1/assets?public_asset=true',
|
||||||
|
null,
|
||||||
|
formData,
|
||||||
|
{
|
||||||
|
headers: {'Content-Type': 'multipart/form-data'}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const assetUrl = `${window.location.origin}/api/v1/assets/${data.id}/thumbnail`
|
||||||
|
this.formData.lnbits_default_bgimage = assetUrl
|
||||||
|
Quasar.Notify.create({
|
||||||
|
type: 'positive',
|
||||||
|
message: 'Background image uploaded.',
|
||||||
|
icon: null
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
LNbits.utils.notifyApiError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -545,31 +545,56 @@ window.PageAccount = {
|
|||||||
if (file) {
|
if (file) {
|
||||||
this.uploadAsset(file)
|
this.uploadAsset(file)
|
||||||
}
|
}
|
||||||
|
e.target.value = null
|
||||||
},
|
},
|
||||||
async uploadAsset(file) {
|
onBackgroundImageInput(e) {
|
||||||
|
const file = e.target.files[0]
|
||||||
|
if (file) {
|
||||||
|
this.uploadBackgroundImage(file)
|
||||||
|
}
|
||||||
|
e.target.value = null
|
||||||
|
},
|
||||||
|
async uploadAsset(
|
||||||
|
file,
|
||||||
|
{isPublic = this.assetsUploadToPublic, notifySuccess = true} = {}
|
||||||
|
) {
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('file', file)
|
formData.append('file', file)
|
||||||
try {
|
try {
|
||||||
await LNbits.api.request(
|
const {data} = await LNbits.api.request(
|
||||||
'POST',
|
'POST',
|
||||||
`/api/v1/assets?public_asset=${this.assetsUploadToPublic}`,
|
`/api/v1/assets?public_asset=${isPublic}`,
|
||||||
null,
|
null,
|
||||||
formData,
|
formData,
|
||||||
{
|
{
|
||||||
headers: {'Content-Type': 'multipart/form-data'}
|
headers: {'Content-Type': 'multipart/form-data'}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
this.$q.notify({
|
if (notifySuccess) {
|
||||||
type: 'positive',
|
this.$q.notify({
|
||||||
message: 'Upload successful!',
|
type: 'positive',
|
||||||
icon: null
|
message: 'Upload successful!',
|
||||||
})
|
icon: null
|
||||||
|
})
|
||||||
|
}
|
||||||
await this.getUserAssets()
|
await this.getUserAssets()
|
||||||
|
return data
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn(e)
|
console.warn(e)
|
||||||
LNbits.utils.notifyApiError(e)
|
LNbits.utils.notifyApiError(e)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async uploadBackgroundImage(file) {
|
||||||
|
const asset = await this.uploadAsset(file, {
|
||||||
|
isPublic: false,
|
||||||
|
notifySuccess: false
|
||||||
|
})
|
||||||
|
if (!asset) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const assetUrl = `${window.location.origin}/api/v1/assets/${asset.id}/thumbnail`
|
||||||
|
await this.siteCustomisationChanged({bgimageChoice: assetUrl})
|
||||||
|
},
|
||||||
async deleteAsset(asset) {
|
async deleteAsset(asset) {
|
||||||
LNbits.utils
|
LNbits.utils
|
||||||
.confirmDialog('Are you sure you want to delete this asset?')
|
.confirmDialog('Are you sure you want to delete this asset?')
|
||||||
|
|||||||
Vendored
+294
-153
File diff suppressed because it is too large
Load Diff
@@ -52,6 +52,7 @@
|
|||||||
:label="prop.label"
|
:label="prop.label"
|
||||||
:hint="prop.hint"
|
:hint="prop.hint"
|
||||||
:value="prop.value"
|
:value="prop.value"
|
||||||
|
:readonly="prop.readonly || false"
|
||||||
>
|
>
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="prop.copy"
|
v-if="prop.copy"
|
||||||
@@ -73,6 +74,15 @@
|
|||||||
></q-btn>
|
></q-btn>
|
||||||
</q-input>
|
</q-input>
|
||||||
</div>
|
</div>
|
||||||
|
<p
|
||||||
|
v-if="fund === 'PhoenixdWallet' && key === 'phoenixd_mnemonic'"
|
||||||
|
class="col-12 q-my-md"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<q-icon name="warning" color="orange" size="xs"></q-icon>
|
||||||
|
<span v-text="$t('phoenixd_warning')"></span>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<q-expansion-item
|
<q-expansion-item
|
||||||
v-if="
|
v-if="
|
||||||
|
|||||||
@@ -251,10 +251,27 @@
|
|||||||
type="text"
|
type="text"
|
||||||
v-model="formData.lnbits_default_bgimage"
|
v-model="formData.lnbits_default_bgimage"
|
||||||
label="Background Image"
|
label="Background Image"
|
||||||
@update:model-value="applyGlobalBgimage"
|
|
||||||
hint="This must be a trusted source. It can change the content and it can log your IP address."
|
hint="This must be a trusted source. It can change the content and it can log your IP address."
|
||||||
>
|
>
|
||||||
|
<template v-slot:append>
|
||||||
|
<q-btn
|
||||||
|
dense
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
icon="upload"
|
||||||
|
@click="$refs.adminBackgroundImageInput.click()"
|
||||||
|
>
|
||||||
|
<q-tooltip>Upload background image</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
ref="adminBackgroundImageInput"
|
||||||
|
accept="image/*"
|
||||||
|
style="display: none"
|
||||||
|
@change="onBackgroundImageInput"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row q-col-gutter-md q-mb-md">
|
<div class="row q-col-gutter-md q-mb-md">
|
||||||
|
|||||||
@@ -492,10 +492,28 @@
|
|||||||
siteCustomisationChanged({bgimageChoice: $event})
|
siteCustomisationChanged({bgimageChoice: $event})
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
<template v-slot:append>
|
||||||
|
<q-btn
|
||||||
|
dense
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
icon="upload"
|
||||||
|
@click="$refs.backgroundImageInput.click()"
|
||||||
|
>
|
||||||
|
<q-tooltip>Upload background image</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</template>
|
||||||
<q-tooltip
|
<q-tooltip
|
||||||
><span v-text="$t('background_image')"></span
|
><span v-text="$t('background_image')"></span
|
||||||
></q-tooltip>
|
></q-tooltip>
|
||||||
</q-input>
|
</q-input>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
ref="backgroundImageInput"
|
||||||
|
accept="image/*"
|
||||||
|
style="display: none"
|
||||||
|
@change="onBackgroundImageInput"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row q-mb-md">
|
<div class="row q-mb-md">
|
||||||
@@ -1108,82 +1126,130 @@
|
|||||||
<q-separator></q-separator>
|
<q-separator></q-separator>
|
||||||
|
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-btn-dropdown
|
<div
|
||||||
color="grey"
|
class="row items-center no-wrap q-col-gutter-sm"
|
||||||
dense
|
|
||||||
outline
|
|
||||||
no-caps
|
|
||||||
:label="props.row.name"
|
|
||||||
:icon="props.row.is_public ? 'public' : ''"
|
|
||||||
>
|
>
|
||||||
<q-list>
|
<div class="col">
|
||||||
<q-item
|
<q-btn-dropdown
|
||||||
clickable
|
color="grey"
|
||||||
v-close-popup
|
dense
|
||||||
@click="copyAssetLinkToClipboard(props.row)"
|
outline
|
||||||
|
no-caps
|
||||||
|
class="full-width"
|
||||||
|
:label="props.row.name"
|
||||||
|
:icon="props.row.is_public ? 'public' : ''"
|
||||||
>
|
>
|
||||||
<q-item-section avatar>
|
<q-list>
|
||||||
<q-avatar icon="content_copy" />
|
<q-item
|
||||||
</q-item-section>
|
clickable
|
||||||
<q-item-section>
|
v-close-popup
|
||||||
<q-item-label>Copy Link</q-item-label>
|
@click="
|
||||||
<q-item-label caption
|
copyAssetLinkToClipboard(props.row)
|
||||||
>Copy asset link to
|
|
||||||
clipboard</q-item-label
|
|
||||||
>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
|
|
||||||
<q-item
|
|
||||||
clickable
|
|
||||||
v-close-popup
|
|
||||||
@click="toggleAssetPublicAccess(props.row)"
|
|
||||||
>
|
|
||||||
<q-item-section avatar>
|
|
||||||
<q-avatar
|
|
||||||
:icon="
|
|
||||||
props.row.is_public
|
|
||||||
? 'public_off'
|
|
||||||
: 'public'
|
|
||||||
"
|
"
|
||||||
text-color="primary"
|
|
||||||
/>
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section v-if="props.row.is_public">
|
|
||||||
<q-item-label>Unpublish</q-item-label>
|
|
||||||
<q-item-label caption
|
|
||||||
>Make this asset private</q-item-label
|
|
||||||
>
|
>
|
||||||
</q-item-section>
|
<q-item-section avatar>
|
||||||
<q-item-section v-else>
|
<q-avatar icon="content_copy" />
|
||||||
<q-item-label>Publish</q-item-label>
|
</q-item-section>
|
||||||
<q-item-label caption
|
<q-item-section>
|
||||||
>Make this asset public</q-item-label
|
<q-item-label>Copy Link</q-item-label>
|
||||||
>
|
<q-item-label caption
|
||||||
</q-item-section>
|
>Copy asset link to
|
||||||
</q-item>
|
clipboard</q-item-label
|
||||||
|
>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
<q-item
|
<q-item
|
||||||
clickable
|
clickable
|
||||||
v-close-popup
|
v-close-popup
|
||||||
@click="deleteAsset(props.row)"
|
@click="
|
||||||
>
|
toggleAssetPublicAccess(props.row)
|
||||||
<q-item-section avatar>
|
"
|
||||||
<q-avatar
|
|
||||||
icon="delete"
|
|
||||||
text-color="negative"
|
|
||||||
/>
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label>Delete</q-item-label>
|
|
||||||
<q-item-label caption
|
|
||||||
>Permanently delete this
|
|
||||||
asset</q-item-label
|
|
||||||
>
|
>
|
||||||
</q-item-section>
|
<q-item-section avatar>
|
||||||
</q-item>
|
<q-avatar
|
||||||
</q-list>
|
:icon="
|
||||||
</q-btn-dropdown>
|
props.row.is_public
|
||||||
|
? 'public_off'
|
||||||
|
: 'public'
|
||||||
|
"
|
||||||
|
text-color="primary"
|
||||||
|
/>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section
|
||||||
|
v-if="props.row.is_public"
|
||||||
|
>
|
||||||
|
<q-item-label>Unpublish</q-item-label>
|
||||||
|
<q-item-label caption
|
||||||
|
>Make this asset
|
||||||
|
private</q-item-label
|
||||||
|
>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section v-else>
|
||||||
|
<q-item-label>Publish</q-item-label>
|
||||||
|
<q-item-label caption
|
||||||
|
>Make this asset
|
||||||
|
public</q-item-label
|
||||||
|
>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<q-item
|
||||||
|
clickable
|
||||||
|
v-close-popup
|
||||||
|
@click="deleteAsset(props.row)"
|
||||||
|
>
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-avatar
|
||||||
|
icon="delete"
|
||||||
|
text-color="negative"
|
||||||
|
/>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>Delete</q-item-label>
|
||||||
|
<q-item-label caption
|
||||||
|
>Permanently delete this
|
||||||
|
asset</q-item-label
|
||||||
|
>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-btn-dropdown>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<q-btn
|
||||||
|
type="a"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
color="primary"
|
||||||
|
dense
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
icon="image"
|
||||||
|
:href="`/api/v1/assets/${props.row.id}/data`"
|
||||||
|
>
|
||||||
|
<q-tooltip>Full image</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="col-auto"
|
||||||
|
v-if="props.row.thumbnail_base64"
|
||||||
|
>
|
||||||
|
<q-btn
|
||||||
|
type="a"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
color="secondary"
|
||||||
|
dense
|
||||||
|
flat
|
||||||
|
round
|
||||||
|
icon="photo_size_select_small"
|
||||||
|
:href="`/api/v1/assets/${props.row.id}/thumbnail`"
|
||||||
|
>
|
||||||
|
<q-tooltip>Thumbnail</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import hashlib
|
|||||||
import json
|
import json
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
from collections.abc import AsyncGenerator
|
from collections.abc import AsyncGenerator
|
||||||
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
from embit.bip39 import mnemonic_is_valid
|
||||||
from httpx import RequestError, TimeoutException
|
from httpx import RequestError, TimeoutException
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from websockets import connect
|
from websockets import connect
|
||||||
@@ -61,6 +63,8 @@ class PhoenixdWallet(Wallet):
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.client = httpx.AsyncClient(base_url=self.endpoint, headers=self.headers)
|
self.client = httpx.AsyncClient(base_url=self.endpoint, headers=self.headers)
|
||||||
|
self._seed_mnemonic_to_persist: str | None = None
|
||||||
|
self._load_mnemonic_from_seed_file()
|
||||||
|
|
||||||
async def cleanup(self):
|
async def cleanup(self):
|
||||||
try:
|
try:
|
||||||
@@ -69,6 +73,7 @@ class PhoenixdWallet(Wallet):
|
|||||||
logger.warning(f"Error closing wallet connection: {e}")
|
logger.warning(f"Error closing wallet connection: {e}")
|
||||||
|
|
||||||
async def status(self) -> StatusResponse:
|
async def status(self) -> StatusResponse:
|
||||||
|
await self._persist_loaded_mnemonic()
|
||||||
try:
|
try:
|
||||||
r = await self.client.get("/getinfo", timeout=10)
|
r = await self.client.get("/getinfo", timeout=10)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
@@ -101,7 +106,6 @@ class PhoenixdWallet(Wallet):
|
|||||||
unhashed_description: bytes | None = None,
|
unhashed_description: bytes | None = None,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> InvoiceResponse:
|
) -> InvoiceResponse:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
msats_amount = amount
|
msats_amount = amount
|
||||||
data: dict[str, Any] = {
|
data: dict[str, Any] = {
|
||||||
@@ -309,7 +313,7 @@ class PhoenixdWallet(Wallet):
|
|||||||
and message_json.get("type") == "payment_received"
|
and message_json.get("type") == "payment_received"
|
||||||
):
|
):
|
||||||
logger.info(
|
logger.info(
|
||||||
f'payment-received: {message_json["paymentHash"]}'
|
f"payment-received: {message_json['paymentHash']}"
|
||||||
)
|
)
|
||||||
yield message_json["paymentHash"]
|
yield message_json["paymentHash"]
|
||||||
|
|
||||||
@@ -319,3 +323,49 @@ class PhoenixdWallet(Wallet):
|
|||||||
"retrying in 5 seconds"
|
"retrying in 5 seconds"
|
||||||
)
|
)
|
||||||
await asyncio.sleep(5)
|
await asyncio.sleep(5)
|
||||||
|
|
||||||
|
def _load_mnemonic_from_seed_file(self):
|
||||||
|
data_dir = settings.phoenixd_data_dir
|
||||||
|
if not data_dir:
|
||||||
|
return
|
||||||
|
|
||||||
|
seed_path = Path(data_dir).expanduser() / "seed.dat"
|
||||||
|
if not seed_path.is_file():
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
mnemonic = seed_path.read_text(encoding="utf-8").strip()
|
||||||
|
if mnemonic == settings.phoenixd_mnemonic:
|
||||||
|
return
|
||||||
|
except OSError as exc:
|
||||||
|
logger.warning(f"Failed to read Phoenixd seed file '{seed_path}': {exc}")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not mnemonic:
|
||||||
|
logger.warning(f"Phoenixd seed file '{seed_path}' is empty.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if not mnemonic_is_valid(mnemonic):
|
||||||
|
logger.warning(
|
||||||
|
f"Phoenixd seed file '{seed_path}' does not contain a valid "
|
||||||
|
"BIP39 mnemonic."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
settings.phoenixd_mnemonic = mnemonic
|
||||||
|
self._seed_mnemonic_to_persist = mnemonic
|
||||||
|
|
||||||
|
async def _persist_loaded_mnemonic(self):
|
||||||
|
if not self._seed_mnemonic_to_persist:
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.info("Updating 'PHOENIXD_MNEMONIC' mnemonic settings.")
|
||||||
|
try:
|
||||||
|
from lnbits.core.crud.settings import set_settings_field
|
||||||
|
|
||||||
|
await set_settings_field(
|
||||||
|
"phoenixd_mnemonic", self._seed_mnemonic_to_persist
|
||||||
|
)
|
||||||
|
self._seed_mnemonic_to_persist = None
|
||||||
|
except Exception as exc:
|
||||||
|
logger.warning(f"Failed to persist Phoenixd mnemonic: {exc}")
|
||||||
|
|||||||
Generated
+12
-8
@@ -6,7 +6,7 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "lnbits",
|
"name": "lnbits",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.13.5",
|
"axios": "^1.15.0",
|
||||||
"chart.js": "^4.5.1",
|
"chart.js": "^4.5.1",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"nostr-tools": "^2.18.2",
|
"nostr-tools": "^2.18.2",
|
||||||
@@ -734,14 +734,14 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.13.5",
|
"version": "1.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz",
|
||||||
"integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==",
|
"integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.11",
|
"follow-redirects": "^1.15.11",
|
||||||
"form-data": "^4.0.5",
|
"form-data": "^4.0.5",
|
||||||
"proxy-from-env": "^1.1.0"
|
"proxy-from-env": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
@@ -1555,9 +1555,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/proxy-from-env": {
|
"node_modules/proxy-from-env": {
|
||||||
"version": "1.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
|
||||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
"integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pyright": {
|
"node_modules/pyright": {
|
||||||
"version": "1.1.289",
|
"version": "1.1.289",
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@
|
|||||||
"terser": "^5.44.1"
|
"terser": "^5.44.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.13.5",
|
"axios": "^1.15.0",
|
||||||
"chart.js": "^4.5.1",
|
"chart.js": "^4.5.1",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"nostr-tools": "^2.18.2",
|
"nostr-tools": "^2.18.2",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "lnbits"
|
name = "lnbits"
|
||||||
version = "1.5.3"
|
version = "1.5.4-rc1"
|
||||||
requires-python = ">=3.10,<3.13"
|
requires-python = ">=3.10,<3.13"
|
||||||
description = "LNbits, free and open-source Lightning wallet and accounts system."
|
description = "LNbits, free and open-source Lightning wallet and accounts system."
|
||||||
authors = [{ name = "Alan Bits", email = "alan@lnbits.com" }]
|
authors = [{ name = "Alan Bits", email = "alan@lnbits.com" }]
|
||||||
|
|||||||
@@ -1263,7 +1263,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lnbits"
|
name = "lnbits"
|
||||||
version = "1.5.3"
|
version = "1.5.4rc1"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "aiosqlite" },
|
{ name = "aiosqlite" },
|
||||||
@@ -2114,7 +2114,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest"
|
name = "pytest"
|
||||||
version = "9.0.2"
|
version = "9.0.3"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||||
@@ -2125,9 +2125,9 @@ dependencies = [
|
|||||||
{ name = "pygments" },
|
{ name = "pygments" },
|
||||||
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" },
|
{ url = "https://files.pythonhosted.org/packages/d4/24/a372aaf5c9b7208e7112038812994107bc65a84cd00e0354a88c2c77a617/pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9", size = 375249, upload-time = "2026-04-07T17:16:16.13Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2213,11 +2213,11 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "python-multipart"
|
name = "python-multipart"
|
||||||
version = "0.0.22"
|
version = "0.0.26"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/94/01/979e98d542a70714b0cb2b6728ed0b7c46792b695e3eaec3e20711271ca3/python_multipart-0.0.22.tar.gz", hash = "sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58", size = 37612, upload-time = "2026-01-25T10:15:56.219Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/88/71/b145a380824a960ebd60e1014256dbb7d2253f2316ff2d73dfd8928ec2c3/python_multipart-0.0.26.tar.gz", hash = "sha256:08fadc45918cd615e26846437f50c5d6d23304da32c341f289a617127b081f17", size = 43501, upload-time = "2026-04-10T14:09:59.473Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/1b/d0/397f9626e711ff749a95d96b7af99b9c566a9bb5129b8e4c10fc4d100304/python_multipart-0.0.22-py3-none-any.whl", hash = "sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155", size = 24579, upload-time = "2026-01-25T10:15:54.811Z" },
|
{ url = "https://files.pythonhosted.org/packages/9a/22/f1925cdda983ab66fc8ec6ec8014b959262747e58bdca26a4e3d1da29d56/python_multipart-0.0.26-py3-none-any.whl", hash = "sha256:c0b169f8c4484c13b0dcf2ef0ec3a4adb255c4b7d18d8e420477d2b1dd03f185", size = 28847, upload-time = "2026-04-10T14:09:58.131Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
Reference in New Issue
Block a user