mirror of
https://github.com/lnbits/lnbits.git
synced 2025-06-30 10:34:28 +02:00
@ -5,6 +5,21 @@ nav_order: 2
|
|||||||
---
|
---
|
||||||
|
|
||||||
# Basic installation
|
# Basic installation
|
||||||
|
Install Postgres and setup a database for LNbits:
|
||||||
|
```sh
|
||||||
|
# on debian/ubuntu 'sudo apt-get -y install postgresql'
|
||||||
|
# or follow instructions at https://www.postgresql.org/download/linux/
|
||||||
|
|
||||||
|
# Postgres doesn't have a default password, so we'll create one.
|
||||||
|
sudo -i -u postgres
|
||||||
|
psql
|
||||||
|
# on psql
|
||||||
|
ALTER USER postgres PASSWORD 'myPassword'; # choose whatever password you want
|
||||||
|
\q
|
||||||
|
# on postgres user
|
||||||
|
createdb lnbits
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
|
||||||
Download this repo and install the dependencies:
|
Download this repo and install the dependencies:
|
||||||
|
|
||||||
@ -16,7 +31,10 @@ cd lnbits/
|
|||||||
python3 -m venv venv
|
python3 -m venv venv
|
||||||
./venv/bin/pip install -r requirements.txt
|
./venv/bin/pip install -r requirements.txt
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
mkdir data
|
# add the database connection string to .env 'nano .env' LNBITS_DATABASE_URL=
|
||||||
|
# postgres://<user>:<password>@<host>/<database> - alter line bellow with your user, password and db name
|
||||||
|
LNBITS_DATABASE_URL="postgres://postgres:postgres@localhost/lnbits"
|
||||||
|
# save and exit
|
||||||
./venv/bin/uvicorn lnbits.__main__:app --port 5000
|
./venv/bin/uvicorn lnbits.__main__:app --port 5000
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -28,6 +46,10 @@ Then you can restart it and it will be using the new settings.
|
|||||||
|
|
||||||
You might also need to install additional packages or perform additional setup steps, depending on the chosen backend. See [the short guide](./wallets.md) on each different funding source.
|
You might also need to install additional packages or perform additional setup steps, depending on the chosen backend. See [the short guide](./wallets.md) on each different funding source.
|
||||||
|
|
||||||
|
## Important note
|
||||||
|
If you already have LNbits installed and running, we **HIGHLY** recommend you migrate to postgres!
|
||||||
|
You can use the script and instructions on [this guide](https://github.com/talvasconcelos/lnbits-sqlite-to-postgres) to migrate your SQLite database to Postgres.
|
||||||
|
|
||||||
# Additional guides
|
# Additional guides
|
||||||
|
|
||||||
### LNbits running on Umbrel behind Tor
|
### LNbits running on Umbrel behind Tor
|
||||||
|
@ -64,7 +64,7 @@ async def m001_initial(db):
|
|||||||
|
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"""
|
"""
|
||||||
CREATE VIEW IF NOT EXISTS balances AS
|
CREATE VIEW balances AS
|
||||||
SELECT wallet, COALESCE(SUM(s), 0) AS balance FROM (
|
SELECT wallet, COALESCE(SUM(s), 0) AS balance FROM (
|
||||||
SELECT wallet, SUM(amount) AS s -- incoming
|
SELECT wallet, SUM(amount) AS s -- incoming
|
||||||
FROM apipayments
|
FROM apipayments
|
||||||
@ -144,7 +144,7 @@ async def m004_ensure_fees_are_always_negative(db):
|
|||||||
await db.execute("DROP VIEW balances")
|
await db.execute("DROP VIEW balances")
|
||||||
await db.execute(
|
await db.execute(
|
||||||
"""
|
"""
|
||||||
CREATE VIEW IF NOT EXISTS balances AS
|
CREATE VIEW balances AS
|
||||||
SELECT wallet, COALESCE(SUM(s), 0) AS balance FROM (
|
SELECT wallet, COALESCE(SUM(s), 0) AS balance FROM (
|
||||||
SELECT wallet, SUM(amount) AS s -- incoming
|
SELECT wallet, SUM(amount) AS s -- incoming
|
||||||
FROM apipayments
|
FROM apipayments
|
||||||
|
24
lnbits/db.py
24
lnbits/db.py
@ -1,9 +1,10 @@
|
|||||||
import os
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import time
|
|
||||||
import datetime
|
import datetime
|
||||||
from typing import Optional
|
import os
|
||||||
|
import time
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from sqlalchemy_aio.base import AsyncConnection
|
from sqlalchemy_aio.base import AsyncConnection
|
||||||
from sqlalchemy_aio.strategy import ASYNCIO_STRATEGY # type: ignore
|
from sqlalchemy_aio.strategy import ASYNCIO_STRATEGY # type: ignore
|
||||||
@ -93,6 +94,12 @@ class Database(Compat):
|
|||||||
|
|
||||||
import psycopg2 # type: ignore
|
import psycopg2 # type: ignore
|
||||||
|
|
||||||
|
def _parse_timestamp(value, _):
|
||||||
|
f = "%Y-%m-%d %H:%M:%S.%f"
|
||||||
|
if not "." in value:
|
||||||
|
f = "%Y-%m-%d %H:%M:%S"
|
||||||
|
return time.mktime(datetime.datetime.strptime(value, f).timetuple())
|
||||||
|
|
||||||
psycopg2.extensions.register_type(
|
psycopg2.extensions.register_type(
|
||||||
psycopg2.extensions.new_type(
|
psycopg2.extensions.new_type(
|
||||||
psycopg2.extensions.DECIMAL.values,
|
psycopg2.extensions.DECIMAL.values,
|
||||||
@ -114,11 +121,12 @@ class Database(Compat):
|
|||||||
psycopg2.extensions.new_type(
|
psycopg2.extensions.new_type(
|
||||||
(1184, 1114),
|
(1184, 1114),
|
||||||
"TIMESTAMP2INT",
|
"TIMESTAMP2INT",
|
||||||
lambda value, curs: time.mktime(
|
_parse_timestamp
|
||||||
datetime.datetime.strptime(
|
# lambda value, curs: time.mktime(
|
||||||
value, "%Y-%m-%d %H:%M:%S.%f"
|
# datetime.datetime.strptime(
|
||||||
).timetuple()
|
# value, "%Y-%m-%d %H:%M:%S.%f"
|
||||||
),
|
# ).timetuple()
|
||||||
|
# ),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
@ -63,7 +63,7 @@ class LNbitsWallet(Wallet):
|
|||||||
|
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
r = await client.post(
|
r = await client.post(
|
||||||
url=f"{self.endpoint}/api/v1/payments", headers=self.key, json=data
|
url=f"{self.endpoint}/api/v1/payments", headers=self.key, json=data,
|
||||||
)
|
)
|
||||||
ok, checking_id, payment_request, error_message = (
|
ok, checking_id, payment_request, error_message = (
|
||||||
not r.is_error,
|
not r.is_error,
|
||||||
@ -85,7 +85,8 @@ class LNbitsWallet(Wallet):
|
|||||||
r = await client.post(
|
r = await client.post(
|
||||||
url=f"{self.endpoint}/api/v1/payments",
|
url=f"{self.endpoint}/api/v1/payments",
|
||||||
headers=self.key,
|
headers=self.key,
|
||||||
json={"out": True, "bolt11": bolt11},
|
json={"out": True, "bolt11": bolt11},
|
||||||
|
timeout=100,
|
||||||
)
|
)
|
||||||
ok, checking_id, fee_msat, error_message = not r.is_error, None, 0, None
|
ok, checking_id, fee_msat, error_message = not r.is_error, None, 0, None
|
||||||
|
|
||||||
|
@ -80,10 +80,10 @@ class LntxbotWallet(Wallet):
|
|||||||
f"{self.endpoint}/payinvoice",
|
f"{self.endpoint}/payinvoice",
|
||||||
headers=self.auth,
|
headers=self.auth,
|
||||||
json={"invoice": bolt11},
|
json={"invoice": bolt11},
|
||||||
timeout=40,
|
timeout=100,
|
||||||
)
|
)
|
||||||
|
|
||||||
if r.is_error:
|
if "error" in r.json():
|
||||||
try:
|
try:
|
||||||
data = r.json()
|
data = r.json()
|
||||||
error_message = data["message"]
|
error_message = data["message"]
|
||||||
|
Reference in New Issue
Block a user