diff --git a/Dockerfile b/Dockerfile index c4fcb959..fed097d2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,7 @@ FROM python:3.9-slim +RUN apt-get clean RUN apt-get update -RUN apt-get install -y curl +RUN apt-get install -y curl pkg-config build-essential RUN curl -sSL https://install.python-poetry.org | python3 - ENV PATH="/root/.local/bin:$PATH" WORKDIR /app diff --git a/docs/guide/installation.md b/docs/guide/installation.md index 6f9d0d4f..2b058754 100644 --- a/docs/guide/installation.md +++ b/docs/guide/installation.md @@ -12,6 +12,8 @@ By default, LNbits will use SQLite as its database. You can also use PostgreSQL ## Option 1 (recommended): poetry +If you have problems installing LNbits using these instructions, please have a look at the [Troubleshooting](#troubleshooting) section. + ```sh git clone https://github.com/lnbits/lnbits-legend.git cd lnbits-legend/ @@ -26,12 +28,11 @@ curl -sSL https://install.python-poetry.org | python3 - export PATH="/home/ubuntu/.local/bin:$PATH" # or whatever is suggested in the poetry install notes printed to terminal poetry env use python3.9 poetry install --no-dev +poetry run python build.py mkdir data cp .env.example .env -sudo nano .env # set funding source - - +nano .env # set funding source ``` #### Running the server @@ -176,13 +177,15 @@ Problems installing? These commands have helped us install LNbits. ```sh sudo apt install pkg-config libffi-dev libpq-dev +# build essentials for debian/ubuntu +sudo apt install python3.9-dev gcc build-essential + # if the secp256k1 build fails: -# if you used venv -./venv/bin/pip install setuptools wheel # if you used poetry poetry add setuptools wheel -# build essentials for debian/ubuntu -sudo apt install python3-dev gcc build-essential + +# if you used venv +./venv/bin/pip install setuptools wheel ``` ### Optional: PostgreSQL database diff --git a/lnbits/core/crud.py b/lnbits/core/crud.py index 4122f902..ecc27a9c 100644 --- a/lnbits/core/crud.py +++ b/lnbits/core/crud.py @@ -452,6 +452,15 @@ async def delete_payment(checking_id: str, conn: Optional[Connection] = None) -> ) +async def delete_wallet_payment( + checking_id: str, wallet_id: str, conn: Optional[Connection] = None +) -> None: + await (conn or db).execute( + "DELETE FROM apipayments WHERE checking_id = ? AND wallet = ?", + (checking_id, wallet_id), + ) + + async def check_internal( payment_hash: str, conn: Optional[Connection] = None ) -> Optional[str]: diff --git a/lnbits/core/models.py b/lnbits/core/models.py index 4dc15bbc..216acafd 100644 --- a/lnbits/core/models.py +++ b/lnbits/core/models.py @@ -9,6 +9,7 @@ from lnurl import encode as lnurl_encode # type: ignore from loguru import logger from pydantic import BaseModel +from lnbits.db import Connection from lnbits.helpers import url_for from lnbits.settings import WALLET from lnbits.wallets.base import PaymentStatus @@ -131,7 +132,11 @@ class Payment(BaseModel): def is_uncheckable(self) -> bool: return self.checking_id.startswith("internal_") - async def update_status(self, status: PaymentStatus) -> None: + async def update_status( + self, + status: PaymentStatus, + conn: Optional[Connection] = None, + ) -> None: from .crud import update_payment_details await update_payment_details( @@ -139,6 +144,7 @@ class Payment(BaseModel): pending=status.pending, fee=status.fee_msat, preimage=status.preimage, + conn=conn, ) async def set_pending(self, pending: bool) -> None: @@ -146,7 +152,10 @@ class Payment(BaseModel): await update_payment_status(self.checking_id, pending) - async def check_status(self) -> PaymentStatus: + async def check_status( + self, + conn: Optional[Connection] = None, + ) -> PaymentStatus: if self.is_uncheckable: return PaymentStatus(None) @@ -165,18 +174,18 @@ class Payment(BaseModel): logger.warning( f"Deleting outgoing failed payment {self.checking_id}: {status}" ) - await self.delete() + await self.delete(conn) elif not status.pending: logger.info( f"Marking '{'in' if self.is_in else 'out'}' {self.checking_id} as not pending anymore: {status}" ) - await self.update_status(status) + await self.update_status(status, conn=conn) return status - async def delete(self) -> None: + async def delete(self, conn: Optional[Connection] = None) -> None: from .crud import delete_payment - await delete_payment(self.checking_id) + await delete_payment(self.checking_id, conn=conn) class BalanceCheck(BaseModel): diff --git a/lnbits/core/services.py b/lnbits/core/services.py index a6e0b43a..10693f4b 100644 --- a/lnbits/core/services.py +++ b/lnbits/core/services.py @@ -28,7 +28,7 @@ from . import db from .crud import ( check_internal, create_payment, - delete_payment, + delete_wallet_payment, get_wallet, get_wallet_payment, update_payment_details, @@ -221,7 +221,7 @@ async def pay_invoice( logger.warning(f"backend sent payment failure") async with db.connect() as conn: logger.debug(f"deleting temporary payment {temp_id}") - await delete_payment(temp_id, conn=conn) + await delete_wallet_payment(temp_id, wallet_id, conn=conn) raise PaymentFailure( f"payment failed: {payment.error_message}" or "payment failed, but backend didn't give us an error message" diff --git a/lnbits/core/static/js/wallet.js b/lnbits/core/static/js/wallet.js index 1c417eaf..e62c1a6d 100644 --- a/lnbits/core/static/js/wallet.js +++ b/lnbits/core/static/js/wallet.js @@ -369,9 +369,9 @@ new Vue({ decodeRequest: function () { this.parse.show = true let req = this.parse.data.request.toLowerCase() - if (this.parse.data.request.startsWith('lightning:')) { + if (this.parse.data.request.toLowerCase().startsWith('lightning:')) { this.parse.data.request = this.parse.data.request.slice(10) - } else if (this.parse.data.request.startsWith('lnurl:')) { + } else if (this.parse.data.request.toLowerCase().startsWith('lnurl:')) { this.parse.data.request = this.parse.data.request.slice(6) } else if (req.indexOf('lightning=lnurl1') !== -1) { this.parse.data.request = this.parse.data.request diff --git a/lnbits/core/templates/core/wallet.html b/lnbits/core/templates/core/wallet.html index bd2668d1..bccdc2b4 100644 --- a/lnbits/core/templates/core/wallet.html +++ b/lnbits/core/templates/core/wallet.html @@ -711,7 +711,7 @@
Warning

- Login functionality to be released in v0.2, for now, + Login functionality to be released in a future update, for now, make sure you bookmark this page for future access to your wallet Tickets: - row = await db.fetchone("SELECT * FROM events.ticket WHERE id = ?", (payment_hash,)) - if row[6] != True: - await db.execute( - """ - UPDATE events.ticket - SET paid = true - WHERE id = ? - """, - (payment_hash,), - ) - - eventdata = await get_event(row[2]) - assert eventdata, "Couldn't get event from ticket being paid" - - sold = eventdata.sold + 1 - amount_tickets = eventdata.amount_tickets - 1 - await db.execute( - """ - UPDATE events.events - SET sold = ?, amount_tickets = ? - WHERE id = ? - """, - (sold, amount_tickets, row[2]), - ) - - ticket = await get_ticket(payment_hash) - assert ticket, "Newly updated ticket couldn't be retrieved" - return ticket - - async def get_ticket(payment_hash: str) -> Optional[Tickets]: row = await db.fetchone("SELECT * FROM events.ticket WHERE id = ?", (payment_hash,)) return Tickets(**row) if row else None diff --git a/lnbits/extensions/events/views_api.py b/lnbits/extensions/events/views_api.py index 56e6b06c..9cb18f04 100644 --- a/lnbits/extensions/events/views_api.py +++ b/lnbits/extensions/events/views_api.py @@ -24,7 +24,6 @@ from .crud import ( get_ticket, get_tickets, reg_ticket, - set_ticket_paid, update_event, ) diff --git a/lnbits/extensions/offlineshop/wordlists.py b/lnbits/extensions/offlineshop/wordlists.py index ee3663e3..fa0e574d 100644 --- a/lnbits/extensions/offlineshop/wordlists.py +++ b/lnbits/extensions/offlineshop/wordlists.py @@ -5,13 +5,13 @@ animals = [ "duck", "eagle", "flamingo", - "gorila", + "gorilla", "hamster", "iguana", "jaguar", "koala", "llama", - "macaroni penguim", + "macaroni penguin", "numbat", "octopus", "platypus", diff --git a/lnbits/extensions/tpos/templates/tpos/index.html b/lnbits/extensions/tpos/templates/tpos/index.html index edbb2aa8..3c4fa24f 100644 --- a/lnbits/extensions/tpos/templates/tpos/index.html +++ b/lnbits/extensions/tpos/templates/tpos/index.html @@ -138,8 +138,9 @@ hide-dropdown-icon input-debounce="0" new-value-mode="add-unique" - label="Tip % Options" - > + label="Tip % Options (hit enter to add values)" + >Hit enter to add values

@@ -294,6 +294,7 @@ exchangeRate: null, stack: [], tipAmount: 0.0, + hasNFC: false, nfcTagReading: false, invoiceDialog: { show: false, @@ -370,7 +371,7 @@ this.showInvoice() }, submitForm: function () { - if (this.tip_options.length) { + if (this.tip_options && this.tip_options.length) { this.showTipModal() } else { this.showInvoice() @@ -413,9 +414,6 @@ dialog.show = false self.complete.show = true - setTimeout(function () { - self.complete.show = false - }, 5000) } }) }, 3000) diff --git a/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html b/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html index db0811f5..ba52c4fa 100644 --- a/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html +++ b/lnbits/extensions/watchonly/templates/watchonly/_api_docs.html @@ -3,23 +3,36 @@

Onchain Wallet (watch-only) extension uses mempool.space
For use with "account Extended Public Key" - https://iancoleman.io/bip39/ + https://iancoleman.io/bip39/ +
+ Flash binaries + directly from browser
Created by, - Ben Arc (using, Embit
)

- Swagger REST API Documentation

diff --git a/lnbits/tasks.py b/lnbits/tasks.py index 078edca1..41287ff2 100644 --- a/lnbits/tasks.py +++ b/lnbits/tasks.py @@ -103,7 +103,7 @@ async def check_pending_payments(): conn=conn, ) for payment in pending_payments: - await payment.check_status() + await payment.check_status(conn=conn) logger.debug( f"Task: pending check finished for {len(pending_payments)} payments (took {time.time() - start_time:0.3f} s)"