feat: implement automatic crediting of new accounts with 1 million satoshis
- Modified the user account creation process to automatically credit new accounts with 1,000,000 satoshis upon creation. - Updated the `create_user_account_no_ckeck` function to include error handling and logging for the credit operation. - Enhanced tests to verify the balance for newly registered users, ensuring the correct credit amount is applied. - Documented affected account creation paths and testing instructions in the new `AUTO_CREDIT_CHANGES.md` file. fix: pass db connection to update_wallet_balance to prevent SQLite deadlock The auto-credit feature was causing a deadlock on SQLite because update_wallet_balance was opening a new database connection while already inside a transaction. By passing conn=conn, we reuse the existing connection and avoid the deadlock. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
85c7e13a27
commit
51a5adf540
3 changed files with 105 additions and 0 deletions
88
AUTO_CREDIT_CHANGES.md
Normal file
88
AUTO_CREDIT_CHANGES.md
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
# LNBits Auto-Credit Changes
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
Modified LNBits server to automatically credit new accounts with 1 million satoshis (1,000,000 sats) when they are created.
|
||||||
|
|
||||||
|
## Changes Made
|
||||||
|
|
||||||
|
### 1. Modified `lnbits/core/services/users.py`
|
||||||
|
|
||||||
|
**Added imports:**
|
||||||
|
- `get_wallet` from `..crud`
|
||||||
|
- `update_wallet_balance` from `.payments`
|
||||||
|
|
||||||
|
**Modified `create_user_account_no_ckeck` function:**
|
||||||
|
- Changed `create_wallet` call to capture the returned wallet object
|
||||||
|
- Added automatic credit of 1,000,000 sats after wallet creation
|
||||||
|
- Added error handling and logging for the credit operation
|
||||||
|
|
||||||
|
**Code changes:**
|
||||||
|
```python
|
||||||
|
# Before:
|
||||||
|
await create_wallet(
|
||||||
|
user_id=account.id,
|
||||||
|
wallet_name=wallet_name or settings.lnbits_default_wallet_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
# After:
|
||||||
|
wallet = await create_wallet(
|
||||||
|
user_id=account.id,
|
||||||
|
wallet_name=wallet_name or settings.lnbits_default_wallet_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Credit new account with 1 million satoshis
|
||||||
|
try:
|
||||||
|
await update_wallet_balance(wallet, 1_000_000)
|
||||||
|
logger.info(f"Credited new account {account.id} with 1,000,000 sats")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to credit new account {account.id} with 1,000,000 sats: {e}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Updated Tests in `tests/api/test_auth.py`
|
||||||
|
|
||||||
|
**Modified test functions:**
|
||||||
|
- `test_register_ok`: Added balance verification for regular user registration
|
||||||
|
- `test_register_nostr_ok`: Added balance verification for Nostr authentication
|
||||||
|
|
||||||
|
**Added assertions:**
|
||||||
|
```python
|
||||||
|
# Check that the wallet has 1 million satoshis
|
||||||
|
wallet = user.wallets[0]
|
||||||
|
assert wallet.balance == 1_000_000, f"Expected 1,000,000 sats balance, got {wallet.balance} sats"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Affected Account Creation Paths
|
||||||
|
|
||||||
|
The automatic credit will be applied to all new accounts created through:
|
||||||
|
|
||||||
|
1. **Regular user registration** (`/api/v1/auth/register`)
|
||||||
|
2. **Nostr authentication** (`/api/v1/auth/nostr`)
|
||||||
|
3. **SSO login** (when new account is created)
|
||||||
|
4. **API account creation** (`/api/v1/account`)
|
||||||
|
5. **Admin user creation** (via admin interface)
|
||||||
|
|
||||||
|
## Excluded Paths
|
||||||
|
|
||||||
|
- **Superuser/Admin account creation** (`init_admin_settings`): This function creates the admin account directly and bypasses the user creation flow, so it won't receive the automatic credit.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
To test the changes:
|
||||||
|
|
||||||
|
1. Install dependencies: `poetry install`
|
||||||
|
2. Run the modified tests: `poetry run pytest tests/api/test_auth.py::test_register_ok -v`
|
||||||
|
3. Run Nostr test: `poetry run pytest tests/api/test_auth.py::test_register_nostr_ok -v`
|
||||||
|
|
||||||
|
## Logging
|
||||||
|
|
||||||
|
The system will log:
|
||||||
|
- Success: `"Credited new account {account.id} with 1,000,000 sats"`
|
||||||
|
- Failure: `"Failed to credit new account {account.id} with 1,000,000 sats: {error}"`
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- The credit uses the existing `update_wallet_balance` function which creates an internal payment record
|
||||||
|
- The credit is applied after wallet creation but before user extensions are set up
|
||||||
|
- Error handling ensures that account creation continues even if the credit fails
|
||||||
|
- The credit amount is hardcoded to 1,000,000 sats (1MM sats)
|
||||||
|
|
||||||
|
|
@ -26,6 +26,7 @@ from ..crud import (
|
||||||
get_super_settings,
|
get_super_settings,
|
||||||
get_user_extensions,
|
get_user_extensions,
|
||||||
get_user_from_account,
|
get_user_from_account,
|
||||||
|
get_wallet,
|
||||||
update_account,
|
update_account,
|
||||||
update_super_user,
|
update_super_user,
|
||||||
update_user_extension,
|
update_user_extension,
|
||||||
|
|
@ -37,6 +38,7 @@ from ..models import (
|
||||||
UserExtra,
|
UserExtra,
|
||||||
)
|
)
|
||||||
from .settings import update_cached_settings
|
from .settings import update_cached_settings
|
||||||
|
from .payments import update_wallet_balance
|
||||||
|
|
||||||
|
|
||||||
async def create_user_account(
|
async def create_user_account(
|
||||||
|
|
@ -80,6 +82,13 @@ async def create_user_account_no_ckeck(
|
||||||
conn=conn,
|
conn=conn,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Credit new account with 1 million satoshis
|
||||||
|
try:
|
||||||
|
await update_wallet_balance(wallet, 1_000_000, conn=conn)
|
||||||
|
logger.info(f"Credited new account {account.id} with 1,000,000 sats")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to credit new account {account.id} with 1,000,000 sats: {e}")
|
||||||
|
|
||||||
user_extensions = (default_exts or []) + settings.lnbits_user_default_extensions
|
user_extensions = (default_exts or []) + settings.lnbits_user_default_extensions
|
||||||
for ext_id in user_extensions:
|
for ext_id in user_extensions:
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -296,6 +296,10 @@ async def test_register_ok(http_client: AsyncClient):
|
||||||
len(user.wallets) == 1
|
len(user.wallets) == 1
|
||||||
), f"Expected 1 default wallet, not {len(user.wallets)}."
|
), f"Expected 1 default wallet, not {len(user.wallets)}."
|
||||||
|
|
||||||
|
# Check that the wallet has 1 million satoshis
|
||||||
|
wallet = user.wallets[0]
|
||||||
|
assert wallet.balance == 1_000_000, f"Expected 1,000,000 sats balance, got {wallet.balance} sats"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.anyio
|
@pytest.mark.anyio
|
||||||
async def test_register_email_twice(http_client: AsyncClient):
|
async def test_register_email_twice(http_client: AsyncClient):
|
||||||
|
|
@ -589,6 +593,10 @@ async def test_register_nostr_ok(http_client: AsyncClient, settings: Settings):
|
||||||
len(user.wallets) == 1
|
len(user.wallets) == 1
|
||||||
), f"Expected 1 default wallet, not {len(user.wallets)}."
|
), f"Expected 1 default wallet, not {len(user.wallets)}."
|
||||||
|
|
||||||
|
# Check that the wallet has 1 million satoshis
|
||||||
|
wallet = user.wallets[0]
|
||||||
|
assert wallet.balance == 1_000_000, f"Expected 1,000,000 sats balance, got {wallet.balance} sats"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.anyio
|
@pytest.mark.anyio
|
||||||
async def test_register_nostr_not_allowed(http_client: AsyncClient, settings: Settings):
|
async def test_register_nostr_not_allowed(http_client: AsyncClient, settings: Settings):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue