docs: update functional identifier refs to spirekeeper
Some checks failed
ci.yml / docs: update functional identifier refs to spirekeeper (push) Failing after 0s
Some checks failed
ci.yml / docs: update functional identifier refs to spirekeeper (push) Failing after 0s
Runbook SQL (spirekeeper.dca_*), ext URL paths, code-location paths, and the DB-schema name in docs/CLAUDE/README move to the new identity. Rewrites the placeholder description.md with a real one. Historical aiolabs/satmachineadmin#N issue/repo links stay pointing at the original repo. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a059e3f596
commit
4ac640a499
6 changed files with 142 additions and 143 deletions
|
|
@ -38,7 +38,7 @@
|
|||
-- Find duplicate transactions
|
||||
SELECT transaction_id, COUNT(*) as count,
|
||||
STRING_AGG(id::text, ', ') as record_ids
|
||||
FROM satoshimachine.lamassu_transactions
|
||||
FROM spirekeeper.lamassu_transactions
|
||||
GROUP BY transaction_id
|
||||
HAVING COUNT(*) > 1;
|
||||
```
|
||||
|
|
@ -60,16 +60,16 @@ HAVING COUNT(*) > 1;
|
|||
-- Step 1: Identify duplicate distributions
|
||||
SELECT lt.transaction_id, lt.id, lt.created_at, lt.base_amount,
|
||||
COUNT(dp.id) as distribution_count
|
||||
FROM satoshimachine.lamassu_transactions lt
|
||||
LEFT JOIN satoshimachine.dca_payments dp ON dp.lamassu_transaction_id = lt.id
|
||||
FROM spirekeeper.lamassu_transactions lt
|
||||
LEFT JOIN spirekeeper.dca_payments dp ON dp.lamassu_transaction_id = lt.id
|
||||
GROUP BY lt.id
|
||||
HAVING COUNT(dp.id) > (SELECT COUNT(*) FROM satoshimachine.dca_clients WHERE remaining_balance > 0);
|
||||
HAVING COUNT(dp.id) > (SELECT COUNT(*) FROM spirekeeper.dca_clients WHERE remaining_balance > 0);
|
||||
|
||||
-- Step 2: Calculate over-distributed amounts per client
|
||||
SELECT client_id,
|
||||
SUM(amount_sats) as total_received,
|
||||
-- Manual calculation of expected amount needed here
|
||||
FROM satoshimachine.dca_payments
|
||||
FROM spirekeeper.dca_payments
|
||||
WHERE lamassu_transaction_id IN (SELECT id FROM duplicates_table)
|
||||
GROUP BY client_id;
|
||||
```
|
||||
|
|
@ -94,7 +94,7 @@ if existing:
|
|||
|
||||
**Required Database Change**:
|
||||
```sql
|
||||
ALTER TABLE satoshimachine.lamassu_transactions
|
||||
ALTER TABLE spirekeeper.lamassu_transactions
|
||||
ADD CONSTRAINT unique_transaction_id UNIQUE (transaction_id);
|
||||
```
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ ADD CONSTRAINT unique_transaction_id UNIQUE (transaction_id);
|
|||
-- Check last successful poll
|
||||
SELECT MAX(created_at) as last_transaction,
|
||||
EXTRACT(EPOCH FROM (NOW() - MAX(created_at)))/3600 as hours_since_last
|
||||
FROM satoshimachine.lamassu_transactions;
|
||||
FROM spirekeeper.lamassu_transactions;
|
||||
|
||||
-- If hours_since_last > 24, investigate immediately
|
||||
```
|
||||
|
|
@ -194,8 +194,8 @@ ssh-keygen -t ed25519 -f ~/.ssh/satmachine_lamassu -C "satmachine-polling"
|
|||
-- Find stuck/failed payments (older than 1 hour, not completed)
|
||||
SELECT dp.id, dp.client_id, dp.amount_sats, dp.status, dp.created_at,
|
||||
c.username, dp.payment_hash
|
||||
FROM satoshimachine.dca_payments dp
|
||||
JOIN satoshimachine.dca_clients c ON dp.client_id = c.id
|
||||
FROM spirekeeper.dca_payments dp
|
||||
JOIN spirekeeper.dca_clients c ON dp.client_id = c.id
|
||||
WHERE dp.status != 'completed'
|
||||
AND dp.created_at < NOW() - INTERVAL '1 hour'
|
||||
ORDER BY dp.created_at DESC;
|
||||
|
|
@ -207,7 +207,7 @@ ORDER BY dp.created_at DESC;
|
|||
SELECT
|
||||
SUM(commission_amount) as total_commission_expected,
|
||||
-- Manually check actual wallet balance in LNBits
|
||||
FROM satoshimachine.lamassu_transactions;
|
||||
FROM spirekeeper.lamassu_transactions;
|
||||
```
|
||||
|
||||
#### Immediate Response
|
||||
|
|
@ -258,9 +258,9 @@ SELECT
|
|||
c.remaining_balance,
|
||||
COALESCE(SUM(d.amount), 0) as total_deposits,
|
||||
COALESCE(SUM(CASE WHEN p.status = 'completed' THEN p.amount_sats ELSE 0 END), 0) as total_payments
|
||||
FROM satoshimachine.dca_clients c
|
||||
LEFT JOIN satoshimachine.dca_deposits d ON c.id = d.client_id AND d.status = 'confirmed'
|
||||
LEFT JOIN satoshimachine.dca_payments p ON c.id = p.client_id
|
||||
FROM spirekeeper.dca_clients c
|
||||
LEFT JOIN spirekeeper.dca_deposits d ON c.id = d.client_id AND d.status = 'confirmed'
|
||||
LEFT JOIN spirekeeper.dca_payments p ON c.id = p.client_id
|
||||
GROUP BY c.id;
|
||||
```
|
||||
|
||||
|
|
@ -319,9 +319,9 @@ SELECT
|
|||
COALESCE(SUM(CASE WHEN p.status = 'completed' THEN p.amount_sats ELSE 0 END), 0) as total_distributed,
|
||||
COALESCE(SUM(d.amount), 0) - COALESCE(SUM(CASE WHEN p.status = 'completed' THEN p.amount_sats ELSE 0 END), 0) as calculated_balance,
|
||||
c.remaining_balance - (COALESCE(SUM(d.amount), 0) - COALESCE(SUM(CASE WHEN p.status = 'completed' THEN p.amount_sats ELSE 0 END), 0)) as discrepancy
|
||||
FROM satoshimachine.dca_clients c
|
||||
LEFT JOIN satoshimachine.dca_deposits d ON c.id = d.client_id AND d.status = 'confirmed'
|
||||
LEFT JOIN satoshimachine.dca_payments p ON c.id = p.client_id
|
||||
FROM spirekeeper.dca_clients c
|
||||
LEFT JOIN spirekeeper.dca_deposits d ON c.id = d.client_id AND d.status = 'confirmed'
|
||||
LEFT JOIN spirekeeper.dca_payments p ON c.id = p.client_id
|
||||
GROUP BY c.id, c.username, c.remaining_balance
|
||||
HAVING ABS(c.remaining_balance - (COALESCE(SUM(d.amount), 0) - COALESCE(SUM(CASE WHEN p.status = 'completed' THEN p.amount_sats ELSE 0 END), 0))) > 1;
|
||||
```
|
||||
|
|
@ -341,11 +341,11 @@ HAVING ABS(c.remaining_balance - (COALESCE(SUM(d.amount), 0) - COALESCE(SUM(CASE
|
|||
```sql
|
||||
-- Get complete transaction history for client
|
||||
SELECT 'DEPOSIT' as type, id, amount, status, created_at, confirmed_at
|
||||
FROM satoshimachine.dca_deposits
|
||||
FROM spirekeeper.dca_deposits
|
||||
WHERE client_id = <client_id>
|
||||
UNION ALL
|
||||
SELECT 'PAYMENT' as type, id, amount_sats, status, created_at, NULL
|
||||
FROM satoshimachine.dca_payments
|
||||
FROM spirekeeper.dca_payments
|
||||
WHERE client_id = <client_id>
|
||||
ORDER BY created_at;
|
||||
```
|
||||
|
|
@ -361,18 +361,18 @@ ORDER BY created_at;
|
|||
**Option A: Adjustment Entry** (Recommended)
|
||||
```sql
|
||||
-- Create compensating deposit for positive discrepancy
|
||||
INSERT INTO satoshimachine.dca_deposits (client_id, amount, status, note)
|
||||
INSERT INTO spirekeeper.dca_deposits (client_id, amount, status, note)
|
||||
VALUES (<client_id>, <adjustment_amount>, 'confirmed', 'Balance correction - reconciliation 2025-10-19');
|
||||
|
||||
-- OR Create compensating payment for negative discrepancy
|
||||
INSERT INTO satoshimachine.dca_payments (client_id, amount_sats, status, note)
|
||||
INSERT INTO spirekeeper.dca_payments (client_id, amount_sats, status, note)
|
||||
VALUES (<client_id>, <adjustment_amount>, 'completed', 'Balance correction - reconciliation 2025-10-19');
|
||||
```
|
||||
|
||||
**Option B: Direct Balance Update** (Use with extreme caution)
|
||||
```sql
|
||||
-- ONLY if audit trail is complete and discrepancy is unexplained
|
||||
UPDATE satoshimachine.dca_clients
|
||||
UPDATE spirekeeper.dca_clients
|
||||
SET remaining_balance = <correct_balance>,
|
||||
updated_at = NOW()
|
||||
WHERE id = <client_id>;
|
||||
|
|
@ -396,11 +396,11 @@ async def daily_reconciliation_check():
|
|||
**Database Constraints**:
|
||||
```sql
|
||||
-- Prevent negative balances
|
||||
ALTER TABLE satoshimachine.dca_clients
|
||||
ALTER TABLE spirekeeper.dca_clients
|
||||
ADD CONSTRAINT positive_balance CHECK (remaining_balance >= 0);
|
||||
|
||||
-- Prevent confirmed deposits with zero amount
|
||||
ALTER TABLE satoshimachine.dca_deposits
|
||||
ALTER TABLE spirekeeper.dca_deposits
|
||||
ADD CONSTRAINT positive_deposit CHECK (amount > 0);
|
||||
```
|
||||
|
||||
|
|
@ -435,7 +435,7 @@ SELECT
|
|||
-- Calculate differences
|
||||
base_amount - ROUND(crypto_atoms / (1 + (commission_percentage * (100 - discount) / 100))) as base_difference,
|
||||
commission_amount - ROUND(crypto_atoms - (crypto_atoms / (1 + (commission_percentage * (100 - discount) / 100)))) as commission_difference
|
||||
FROM satoshimachine.lamassu_transactions
|
||||
FROM spirekeeper.lamassu_transactions
|
||||
WHERE ABS(base_amount - ROUND(crypto_atoms / (1 + (commission_percentage * (100 - discount) / 100)))) > 1
|
||||
OR ABS(commission_amount - ROUND(crypto_atoms - (crypto_atoms / (1 + (commission_percentage * (100 - discount) / 100))))) > 1;
|
||||
```
|
||||
|
|
@ -485,9 +485,9 @@ SELECT
|
|||
SUM(lt.base_amount) as total_distributed,
|
||||
SUM(expected_base) as should_have_distributed,
|
||||
SUM(expected_base - lt.base_amount) as client_impact
|
||||
FROM satoshimachine.lamassu_transactions lt
|
||||
JOIN satoshimachine.dca_payments dp ON dp.lamassu_transaction_id = lt.id
|
||||
JOIN satoshimachine.dca_clients c ON dp.client_id = c.id
|
||||
FROM spirekeeper.lamassu_transactions lt
|
||||
JOIN spirekeeper.dca_payments dp ON dp.lamassu_transaction_id = lt.id
|
||||
JOIN spirekeeper.dca_clients c ON dp.client_id = c.id
|
||||
WHERE -- filter for affected transactions
|
||||
GROUP BY c.id;
|
||||
```
|
||||
|
|
@ -505,7 +505,7 @@ GROUP BY c.id;
|
|||
- Create compensating payments to affected clients:
|
||||
```sql
|
||||
-- Add to client balances
|
||||
UPDATE satoshimachine.dca_clients c
|
||||
UPDATE spirekeeper.dca_clients c
|
||||
SET remaining_balance = remaining_balance + adjustment.amount
|
||||
FROM (
|
||||
-- Calculate adjustment per client
|
||||
|
|
@ -572,7 +572,7 @@ assert abs(calculated_total - crypto_atoms) <= 1, "Commission calculation error
|
|||
SELECT
|
||||
SUM(commission_amount) as expected_total_commission,
|
||||
-- Compare to actual wallet balance in LNBits dashboard
|
||||
FROM satoshimachine.lamassu_transactions
|
||||
FROM spirekeeper.lamassu_transactions
|
||||
WHERE created_at > '<date-of-last-known-good-balance>';
|
||||
```
|
||||
|
||||
|
|
@ -607,7 +607,7 @@ curl -X GET https://<lnbits-host>/api/v1/wallet \
|
|||
SELECT commission_wallet_id,
|
||||
LEFT(commission_wallet_adminkey, 10) || '...' as key_preview,
|
||||
updated_at
|
||||
FROM satoshimachine.lamassu_config
|
||||
FROM spirekeeper.lamassu_config
|
||||
ORDER BY updated_at DESC
|
||||
LIMIT 1;
|
||||
```
|
||||
|
|
@ -783,9 +783,9 @@ WITH client_financials AS (
|
|||
COALESCE(SUM(CASE WHEN p.status = 'completed' THEN p.amount_sats ELSE 0 END), 0) as total_payments,
|
||||
COUNT(DISTINCT d.id) as deposit_count,
|
||||
COUNT(DISTINCT p.id) as payment_count
|
||||
FROM satoshimachine.dca_clients c
|
||||
LEFT JOIN satoshimachine.dca_deposits d ON c.id = d.client_id AND d.status = 'confirmed'
|
||||
LEFT JOIN satoshimachine.dca_payments p ON c.id = p.client_id
|
||||
FROM spirekeeper.dca_clients c
|
||||
LEFT JOIN spirekeeper.dca_deposits d ON c.id = d.client_id AND d.status = 'confirmed'
|
||||
LEFT JOIN spirekeeper.dca_payments p ON c.id = p.client_id
|
||||
GROUP BY c.id
|
||||
)
|
||||
SELECT
|
||||
|
|
@ -813,7 +813,7 @@ SELECT
|
|||
SUM(commission_amount) as total_commission,
|
||||
MIN(created_at) as first_transaction,
|
||||
MAX(created_at) as last_transaction
|
||||
FROM satoshimachine.lamassu_transactions;
|
||||
FROM spirekeeper.lamassu_transactions;
|
||||
|
||||
-- 3. Failed/Pending Payments Check
|
||||
SELECT
|
||||
|
|
@ -822,7 +822,7 @@ SELECT
|
|||
SUM(amount_sats) as total_amount,
|
||||
MIN(created_at) as oldest,
|
||||
MAX(created_at) as newest
|
||||
FROM satoshimachine.dca_payments
|
||||
FROM spirekeeper.dca_payments
|
||||
GROUP BY status
|
||||
ORDER BY
|
||||
CASE status
|
||||
|
|
@ -839,7 +839,7 @@ SELECT
|
|||
status,
|
||||
created_at,
|
||||
EXTRACT(EPOCH FROM (NOW() - created_at))/3600 as hours_pending
|
||||
FROM satoshimachine.dca_deposits
|
||||
FROM spirekeeper.dca_deposits
|
||||
WHERE status = 'pending'
|
||||
AND created_at < NOW() - INTERVAL '48 hours'
|
||||
ORDER BY created_at;
|
||||
|
|
@ -855,7 +855,7 @@ SELECT
|
|||
commission_amount,
|
||||
ROUND(crypto_atoms / (1 + (commission_percentage * (100 - discount) / 100))) as expected_base,
|
||||
base_amount - ROUND(crypto_atoms / (1 + (commission_percentage * (100 - discount) / 100))) as difference
|
||||
FROM satoshimachine.lamassu_transactions
|
||||
FROM spirekeeper.lamassu_transactions
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 20;
|
||||
```
|
||||
|
|
@ -876,15 +876,15 @@ psql -h localhost -U lnbits -d lnbits
|
|||
2. **Direct Configuration Update**:
|
||||
```sql
|
||||
-- Update Lamassu config directly
|
||||
UPDATE satoshimachine.lamassu_config
|
||||
UPDATE spirekeeper.lamassu_config
|
||||
SET polling_enabled = false
|
||||
WHERE id = (SELECT MAX(id) FROM satoshimachine.lamassu_config);
|
||||
WHERE id = (SELECT MAX(id) FROM spirekeeper.lamassu_config);
|
||||
```
|
||||
|
||||
3. **Manual Client Balance Update**:
|
||||
```sql
|
||||
-- ONLY in emergency when dashboard unavailable
|
||||
UPDATE satoshimachine.dca_clients
|
||||
UPDATE spirekeeper.dca_clients
|
||||
SET remaining_balance = <correct_amount>
|
||||
WHERE id = <client_id>;
|
||||
-- MUST document this action in incident log
|
||||
|
|
@ -910,19 +910,19 @@ uv run lnbits
|
|||
```bash
|
||||
# Export all DCA-related tables to CSV
|
||||
sqlite3 -header -csv /path/to/lnbits/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.lamassu_transactions;" \
|
||||
"SELECT * FROM spirekeeper.lamassu_transactions;" \
|
||||
> lamassu_transactions_export_$(date +%Y%m%d_%H%M%S).csv
|
||||
|
||||
sqlite3 -header -csv /path/to/lnbits/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.dca_payments;" \
|
||||
"SELECT * FROM spirekeeper.dca_payments;" \
|
||||
> dca_payments_export_$(date +%Y%m%d_%H%M%S).csv
|
||||
|
||||
sqlite3 -header -csv /path/to/lnbits/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.dca_deposits;" \
|
||||
"SELECT * FROM spirekeeper.dca_deposits;" \
|
||||
> dca_deposits_export_$(date +%Y%m%d_%H%M%S).csv
|
||||
|
||||
sqlite3 -header -csv /path/to/lnbits/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.dca_clients;" \
|
||||
"SELECT * FROM spirekeeper.dca_clients;" \
|
||||
> dca_clients_export_$(date +%Y%m%d_%H%M%S).csv
|
||||
```
|
||||
|
||||
|
|
@ -946,9 +946,9 @@ SELECT
|
|||
dp.amount_sats as client_received,
|
||||
dp.status as payment_status,
|
||||
dp.payment_hash
|
||||
FROM satoshimachine.lamassu_transactions lt
|
||||
LEFT JOIN satoshimachine.dca_payments dp ON dp.lamassu_transaction_id = lt.id
|
||||
LEFT JOIN satoshimachine.dca_clients c ON dp.client_id = c.id
|
||||
FROM spirekeeper.lamassu_transactions lt
|
||||
LEFT JOIN spirekeeper.dca_payments dp ON dp.lamassu_transaction_id = lt.id
|
||||
LEFT JOIN spirekeeper.dca_clients c ON dp.client_id = c.id
|
||||
ORDER BY lt.created_at DESC, c.username;
|
||||
```
|
||||
|
||||
|
|
@ -981,18 +981,18 @@ async def process_lamassu_transaction(txn_data: dict) -> Optional[LamassuTransac
|
|||
|
||||
```sql
|
||||
-- Add unique constraint on transaction_id
|
||||
ALTER TABLE satoshimachine.lamassu_transactions
|
||||
ALTER TABLE spirekeeper.lamassu_transactions
|
||||
ADD CONSTRAINT unique_transaction_id UNIQUE (transaction_id);
|
||||
|
||||
-- Prevent negative balances
|
||||
ALTER TABLE satoshimachine.dca_clients
|
||||
ALTER TABLE spirekeeper.dca_clients
|
||||
ADD CONSTRAINT positive_balance CHECK (remaining_balance >= 0);
|
||||
|
||||
-- Ensure positive amounts
|
||||
ALTER TABLE satoshimachine.dca_deposits
|
||||
ALTER TABLE spirekeeper.dca_deposits
|
||||
ADD CONSTRAINT positive_deposit CHECK (amount > 0);
|
||||
|
||||
ALTER TABLE satoshimachine.dca_payments
|
||||
ALTER TABLE spirekeeper.dca_payments
|
||||
ADD CONSTRAINT positive_payment CHECK (amount_sats > 0);
|
||||
```
|
||||
|
||||
|
|
@ -1196,7 +1196,7 @@ grep "wallet.*api\|payment_hash" lnbits.log | tail -50
|
|||
### System Access
|
||||
|
||||
**LNBits Admin Dashboard**:
|
||||
- URL: `https://<your-lnbits-host>/satoshimachine`
|
||||
- URL: `https://<your-lnbits-host>/spirekeeper`
|
||||
- Requires superuser authentication
|
||||
|
||||
**Database Access**:
|
||||
|
|
@ -1205,7 +1205,7 @@ grep "wallet.*api\|payment_hash" lnbits.log | tail -50
|
|||
sqlite3 /home/padreug/AioLabs/Git/lnbits-extensions/lnbits/data/database.sqlite
|
||||
|
||||
# Direct table access
|
||||
sqlite3 /path/to/db "SELECT * FROM satoshimachine.<table_name>;"
|
||||
sqlite3 /path/to/db "SELECT * FROM spirekeeper.<table_name>;"
|
||||
```
|
||||
|
||||
**Log Files**:
|
||||
|
|
@ -1274,7 +1274,7 @@ pkill -f lnbits
|
|||
|
||||
```sql
|
||||
-- Disable automatic polling
|
||||
UPDATE satoshimachine.lamassu_config
|
||||
UPDATE spirekeeper.lamassu_config
|
||||
SET polling_enabled = false;
|
||||
```
|
||||
|
||||
|
|
@ -1283,7 +1283,7 @@ SET polling_enabled = false;
|
|||
```sql
|
||||
-- All client balances summary
|
||||
SELECT id, username, remaining_balance, created_at
|
||||
FROM satoshimachine.dca_clients
|
||||
FROM spirekeeper.dca_clients
|
||||
ORDER BY remaining_balance DESC;
|
||||
```
|
||||
|
||||
|
|
@ -1291,7 +1291,7 @@ ORDER BY remaining_balance DESC;
|
|||
|
||||
```sql
|
||||
SELECT id, transaction_id, created_at, crypto_atoms, base_amount, commission_amount
|
||||
FROM satoshimachine.lamassu_transactions
|
||||
FROM spirekeeper.lamassu_transactions
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 10;
|
||||
```
|
||||
|
|
@ -1299,7 +1299,7 @@ LIMIT 10;
|
|||
### Failed Payments
|
||||
|
||||
```sql
|
||||
SELECT * FROM satoshimachine.dca_payments
|
||||
SELECT * FROM spirekeeper.dca_payments
|
||||
WHERE status != 'completed'
|
||||
ORDER BY created_at DESC;
|
||||
```
|
||||
|
|
@ -1314,19 +1314,19 @@ BACKUP_DIR="emergency_backup_${DATE}"
|
|||
mkdir -p $BACKUP_DIR
|
||||
|
||||
sqlite3 -header -csv /path/to/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.lamassu_transactions;" \
|
||||
"SELECT * FROM spirekeeper.lamassu_transactions;" \
|
||||
> ${BACKUP_DIR}/lamassu_transactions.csv
|
||||
|
||||
sqlite3 -header -csv /path/to/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.dca_payments;" \
|
||||
"SELECT * FROM spirekeeper.dca_payments;" \
|
||||
> ${BACKUP_DIR}/dca_payments.csv
|
||||
|
||||
sqlite3 -header -csv /path/to/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.dca_deposits;" \
|
||||
"SELECT * FROM spirekeeper.dca_deposits;" \
|
||||
> ${BACKUP_DIR}/dca_deposits.csv
|
||||
|
||||
sqlite3 -header -csv /path/to/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.dca_clients;" \
|
||||
"SELECT * FROM spirekeeper.dca_clients;" \
|
||||
> ${BACKUP_DIR}/dca_clients.csv
|
||||
|
||||
echo "Backup complete in ${BACKUP_DIR}/"
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
-- Find duplicate transactions
|
||||
SELECT transaction_id, COUNT(*) as count,
|
||||
STRING_AGG(id::text, ', ') as record_ids
|
||||
FROM satoshimachine.lamassu_transactions
|
||||
FROM spirekeeper.lamassu_transactions
|
||||
GROUP BY transaction_id
|
||||
HAVING COUNT(*) > 1;
|
||||
```
|
||||
|
|
@ -60,16 +60,16 @@ HAVING COUNT(*) > 1;
|
|||
-- Step 1: Identify duplicate distributions
|
||||
SELECT lt.transaction_id, lt.id, lt.created_at, lt.base_amount,
|
||||
COUNT(dp.id) as distribution_count
|
||||
FROM satoshimachine.lamassu_transactions lt
|
||||
LEFT JOIN satoshimachine.dca_payments dp ON dp.lamassu_transaction_id = lt.id
|
||||
FROM spirekeeper.lamassu_transactions lt
|
||||
LEFT JOIN spirekeeper.dca_payments dp ON dp.lamassu_transaction_id = lt.id
|
||||
GROUP BY lt.id
|
||||
HAVING COUNT(dp.id) > (SELECT COUNT(*) FROM satoshimachine.dca_clients WHERE remaining_balance > 0);
|
||||
HAVING COUNT(dp.id) > (SELECT COUNT(*) FROM spirekeeper.dca_clients WHERE remaining_balance > 0);
|
||||
|
||||
-- Step 2: Calculate over-distributed amounts per client
|
||||
SELECT client_id,
|
||||
SUM(amount_sats) as total_received,
|
||||
-- Manual calculation of expected amount needed here
|
||||
FROM satoshimachine.dca_payments
|
||||
FROM spirekeeper.dca_payments
|
||||
WHERE lamassu_transaction_id IN (SELECT id FROM duplicates_table)
|
||||
GROUP BY client_id;
|
||||
```
|
||||
|
|
@ -94,7 +94,7 @@ if existing:
|
|||
|
||||
**Required Database Change**:
|
||||
```sql
|
||||
ALTER TABLE satoshimachine.lamassu_transactions
|
||||
ALTER TABLE spirekeeper.lamassu_transactions
|
||||
ADD CONSTRAINT unique_transaction_id UNIQUE (transaction_id);
|
||||
```
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ ADD CONSTRAINT unique_transaction_id UNIQUE (transaction_id);
|
|||
-- Check last successful poll
|
||||
SELECT MAX(created_at) as last_transaction,
|
||||
EXTRACT(EPOCH FROM (NOW() - MAX(created_at)))/3600 as hours_since_last
|
||||
FROM satoshimachine.lamassu_transactions;
|
||||
FROM spirekeeper.lamassu_transactions;
|
||||
|
||||
-- If hours_since_last > 24, investigate immediately
|
||||
```
|
||||
|
|
@ -194,8 +194,8 @@ ssh-keygen -t ed25519 -f ~/.ssh/satmachine_lamassu -C "satmachine-polling"
|
|||
-- Find stuck/failed payments (older than 1 hour, not completed)
|
||||
SELECT dp.id, dp.client_id, dp.amount_sats, dp.status, dp.created_at,
|
||||
c.username, dp.payment_hash
|
||||
FROM satoshimachine.dca_payments dp
|
||||
JOIN satoshimachine.dca_clients c ON dp.client_id = c.id
|
||||
FROM spirekeeper.dca_payments dp
|
||||
JOIN spirekeeper.dca_clients c ON dp.client_id = c.id
|
||||
WHERE dp.status != 'completed'
|
||||
AND dp.created_at < NOW() - INTERVAL '1 hour'
|
||||
ORDER BY dp.created_at DESC;
|
||||
|
|
@ -207,7 +207,7 @@ ORDER BY dp.created_at DESC;
|
|||
SELECT
|
||||
SUM(commission_amount) as total_commission_expected,
|
||||
-- Manually check actual wallet balance in LNBits
|
||||
FROM satoshimachine.lamassu_transactions;
|
||||
FROM spirekeeper.lamassu_transactions;
|
||||
```
|
||||
|
||||
#### Immediate Response
|
||||
|
|
@ -258,9 +258,9 @@ SELECT
|
|||
c.remaining_balance,
|
||||
COALESCE(SUM(d.amount), 0) as total_deposits,
|
||||
COALESCE(SUM(CASE WHEN p.status = 'completed' THEN p.amount_sats ELSE 0 END), 0) as total_payments
|
||||
FROM satoshimachine.dca_clients c
|
||||
LEFT JOIN satoshimachine.dca_deposits d ON c.id = d.client_id AND d.status = 'confirmed'
|
||||
LEFT JOIN satoshimachine.dca_payments p ON c.id = p.client_id
|
||||
FROM spirekeeper.dca_clients c
|
||||
LEFT JOIN spirekeeper.dca_deposits d ON c.id = d.client_id AND d.status = 'confirmed'
|
||||
LEFT JOIN spirekeeper.dca_payments p ON c.id = p.client_id
|
||||
GROUP BY c.id;
|
||||
```
|
||||
|
||||
|
|
@ -319,9 +319,9 @@ SELECT
|
|||
COALESCE(SUM(CASE WHEN p.status = 'completed' THEN p.amount_sats ELSE 0 END), 0) as total_distributed,
|
||||
COALESCE(SUM(d.amount), 0) - COALESCE(SUM(CASE WHEN p.status = 'completed' THEN p.amount_sats ELSE 0 END), 0) as calculated_balance,
|
||||
c.remaining_balance - (COALESCE(SUM(d.amount), 0) - COALESCE(SUM(CASE WHEN p.status = 'completed' THEN p.amount_sats ELSE 0 END), 0)) as discrepancy
|
||||
FROM satoshimachine.dca_clients c
|
||||
LEFT JOIN satoshimachine.dca_deposits d ON c.id = d.client_id AND d.status = 'confirmed'
|
||||
LEFT JOIN satoshimachine.dca_payments p ON c.id = p.client_id
|
||||
FROM spirekeeper.dca_clients c
|
||||
LEFT JOIN spirekeeper.dca_deposits d ON c.id = d.client_id AND d.status = 'confirmed'
|
||||
LEFT JOIN spirekeeper.dca_payments p ON c.id = p.client_id
|
||||
GROUP BY c.id, c.username, c.remaining_balance
|
||||
HAVING ABS(c.remaining_balance - (COALESCE(SUM(d.amount), 0) - COALESCE(SUM(CASE WHEN p.status = 'completed' THEN p.amount_sats ELSE 0 END), 0))) > 1;
|
||||
```
|
||||
|
|
@ -341,11 +341,11 @@ HAVING ABS(c.remaining_balance - (COALESCE(SUM(d.amount), 0) - COALESCE(SUM(CASE
|
|||
```sql
|
||||
-- Get complete transaction history for client
|
||||
SELECT 'DEPOSIT' as type, id, amount, status, created_at, confirmed_at
|
||||
FROM satoshimachine.dca_deposits
|
||||
FROM spirekeeper.dca_deposits
|
||||
WHERE client_id = <client_id>
|
||||
UNION ALL
|
||||
SELECT 'PAYMENT' as type, id, amount_sats, status, created_at, NULL
|
||||
FROM satoshimachine.dca_payments
|
||||
FROM spirekeeper.dca_payments
|
||||
WHERE client_id = <client_id>
|
||||
ORDER BY created_at;
|
||||
```
|
||||
|
|
@ -361,18 +361,18 @@ ORDER BY created_at;
|
|||
**Option A: Adjustment Entry** (Recommended)
|
||||
```sql
|
||||
-- Create compensating deposit for positive discrepancy
|
||||
INSERT INTO satoshimachine.dca_deposits (client_id, amount, status, note)
|
||||
INSERT INTO spirekeeper.dca_deposits (client_id, amount, status, note)
|
||||
VALUES (<client_id>, <adjustment_amount>, 'confirmed', 'Balance correction - reconciliation 2025-10-19');
|
||||
|
||||
-- OR Create compensating payment for negative discrepancy
|
||||
INSERT INTO satoshimachine.dca_payments (client_id, amount_sats, status, note)
|
||||
INSERT INTO spirekeeper.dca_payments (client_id, amount_sats, status, note)
|
||||
VALUES (<client_id>, <adjustment_amount>, 'completed', 'Balance correction - reconciliation 2025-10-19');
|
||||
```
|
||||
|
||||
**Option B: Direct Balance Update** (Use with extreme caution)
|
||||
```sql
|
||||
-- ONLY if audit trail is complete and discrepancy is unexplained
|
||||
UPDATE satoshimachine.dca_clients
|
||||
UPDATE spirekeeper.dca_clients
|
||||
SET remaining_balance = <correct_balance>,
|
||||
updated_at = NOW()
|
||||
WHERE id = <client_id>;
|
||||
|
|
@ -396,11 +396,11 @@ async def daily_reconciliation_check():
|
|||
**Database Constraints**:
|
||||
```sql
|
||||
-- Prevent negative balances
|
||||
ALTER TABLE satoshimachine.dca_clients
|
||||
ALTER TABLE spirekeeper.dca_clients
|
||||
ADD CONSTRAINT positive_balance CHECK (remaining_balance >= 0);
|
||||
|
||||
-- Prevent confirmed deposits with zero amount
|
||||
ALTER TABLE satoshimachine.dca_deposits
|
||||
ALTER TABLE spirekeeper.dca_deposits
|
||||
ADD CONSTRAINT positive_deposit CHECK (amount > 0);
|
||||
```
|
||||
|
||||
|
|
@ -435,7 +435,7 @@ SELECT
|
|||
-- Calculate differences
|
||||
base_amount - ROUND(crypto_atoms / (1 + (commission_percentage * (100 - discount) / 100))) as base_difference,
|
||||
commission_amount - ROUND(crypto_atoms - (crypto_atoms / (1 + (commission_percentage * (100 - discount) / 100)))) as commission_difference
|
||||
FROM satoshimachine.lamassu_transactions
|
||||
FROM spirekeeper.lamassu_transactions
|
||||
WHERE ABS(base_amount - ROUND(crypto_atoms / (1 + (commission_percentage * (100 - discount) / 100)))) > 1
|
||||
OR ABS(commission_amount - ROUND(crypto_atoms - (crypto_atoms / (1 + (commission_percentage * (100 - discount) / 100))))) > 1;
|
||||
```
|
||||
|
|
@ -485,9 +485,9 @@ SELECT
|
|||
SUM(lt.base_amount) as total_distributed,
|
||||
SUM(expected_base) as should_have_distributed,
|
||||
SUM(expected_base - lt.base_amount) as client_impact
|
||||
FROM satoshimachine.lamassu_transactions lt
|
||||
JOIN satoshimachine.dca_payments dp ON dp.lamassu_transaction_id = lt.id
|
||||
JOIN satoshimachine.dca_clients c ON dp.client_id = c.id
|
||||
FROM spirekeeper.lamassu_transactions lt
|
||||
JOIN spirekeeper.dca_payments dp ON dp.lamassu_transaction_id = lt.id
|
||||
JOIN spirekeeper.dca_clients c ON dp.client_id = c.id
|
||||
WHERE -- filter for affected transactions
|
||||
GROUP BY c.id;
|
||||
```
|
||||
|
|
@ -505,7 +505,7 @@ GROUP BY c.id;
|
|||
- Create compensating payments to affected clients:
|
||||
```sql
|
||||
-- Add to client balances
|
||||
UPDATE satoshimachine.dca_clients c
|
||||
UPDATE spirekeeper.dca_clients c
|
||||
SET remaining_balance = remaining_balance + adjustment.amount
|
||||
FROM (
|
||||
-- Calculate adjustment per client
|
||||
|
|
@ -572,7 +572,7 @@ assert abs(calculated_total - crypto_atoms) <= 1, "Commission calculation error
|
|||
SELECT
|
||||
SUM(commission_amount) as expected_total_commission,
|
||||
-- Compare to actual wallet balance in LNBits dashboard
|
||||
FROM satoshimachine.lamassu_transactions
|
||||
FROM spirekeeper.lamassu_transactions
|
||||
WHERE created_at > '<date-of-last-known-good-balance>';
|
||||
```
|
||||
|
||||
|
|
@ -607,7 +607,7 @@ curl -X GET https://<lnbits-host>/api/v1/wallet \
|
|||
SELECT commission_wallet_id,
|
||||
LEFT(commission_wallet_adminkey, 10) || '...' as key_preview,
|
||||
updated_at
|
||||
FROM satoshimachine.lamassu_config
|
||||
FROM spirekeeper.lamassu_config
|
||||
ORDER BY updated_at DESC
|
||||
LIMIT 1;
|
||||
```
|
||||
|
|
@ -783,9 +783,9 @@ WITH client_financials AS (
|
|||
COALESCE(SUM(CASE WHEN p.status = 'completed' THEN p.amount_sats ELSE 0 END), 0) as total_payments,
|
||||
COUNT(DISTINCT d.id) as deposit_count,
|
||||
COUNT(DISTINCT p.id) as payment_count
|
||||
FROM satoshimachine.dca_clients c
|
||||
LEFT JOIN satoshimachine.dca_deposits d ON c.id = d.client_id AND d.status = 'confirmed'
|
||||
LEFT JOIN satoshimachine.dca_payments p ON c.id = p.client_id
|
||||
FROM spirekeeper.dca_clients c
|
||||
LEFT JOIN spirekeeper.dca_deposits d ON c.id = d.client_id AND d.status = 'confirmed'
|
||||
LEFT JOIN spirekeeper.dca_payments p ON c.id = p.client_id
|
||||
GROUP BY c.id
|
||||
)
|
||||
SELECT
|
||||
|
|
@ -813,7 +813,7 @@ SELECT
|
|||
SUM(commission_amount) as total_commission,
|
||||
MIN(created_at) as first_transaction,
|
||||
MAX(created_at) as last_transaction
|
||||
FROM satoshimachine.lamassu_transactions;
|
||||
FROM spirekeeper.lamassu_transactions;
|
||||
|
||||
-- 3. Failed/Pending Payments Check
|
||||
SELECT
|
||||
|
|
@ -822,7 +822,7 @@ SELECT
|
|||
SUM(amount_sats) as total_amount,
|
||||
MIN(created_at) as oldest,
|
||||
MAX(created_at) as newest
|
||||
FROM satoshimachine.dca_payments
|
||||
FROM spirekeeper.dca_payments
|
||||
GROUP BY status
|
||||
ORDER BY
|
||||
CASE status
|
||||
|
|
@ -839,7 +839,7 @@ SELECT
|
|||
status,
|
||||
created_at,
|
||||
EXTRACT(EPOCH FROM (NOW() - created_at))/3600 as hours_pending
|
||||
FROM satoshimachine.dca_deposits
|
||||
FROM spirekeeper.dca_deposits
|
||||
WHERE status = 'pending'
|
||||
AND created_at < NOW() - INTERVAL '48 hours'
|
||||
ORDER BY created_at;
|
||||
|
|
@ -855,7 +855,7 @@ SELECT
|
|||
commission_amount,
|
||||
ROUND(crypto_atoms / (1 + (commission_percentage * (100 - discount) / 100))) as expected_base,
|
||||
base_amount - ROUND(crypto_atoms / (1 + (commission_percentage * (100 - discount) / 100))) as difference
|
||||
FROM satoshimachine.lamassu_transactions
|
||||
FROM spirekeeper.lamassu_transactions
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 20;
|
||||
```
|
||||
|
|
@ -876,15 +876,15 @@ psql -h localhost -U lnbits -d lnbits
|
|||
2. **Direct Configuration Update**:
|
||||
```sql
|
||||
-- Update Lamassu config directly
|
||||
UPDATE satoshimachine.lamassu_config
|
||||
UPDATE spirekeeper.lamassu_config
|
||||
SET polling_enabled = false
|
||||
WHERE id = (SELECT MAX(id) FROM satoshimachine.lamassu_config);
|
||||
WHERE id = (SELECT MAX(id) FROM spirekeeper.lamassu_config);
|
||||
```
|
||||
|
||||
3. **Manual Client Balance Update**:
|
||||
```sql
|
||||
-- ONLY in emergency when dashboard unavailable
|
||||
UPDATE satoshimachine.dca_clients
|
||||
UPDATE spirekeeper.dca_clients
|
||||
SET remaining_balance = <correct_amount>
|
||||
WHERE id = <client_id>;
|
||||
-- MUST document this action in incident log
|
||||
|
|
@ -910,19 +910,19 @@ uv run lnbits
|
|||
```bash
|
||||
# Export all DCA-related tables to CSV
|
||||
sqlite3 -header -csv /path/to/lnbits/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.lamassu_transactions;" \
|
||||
"SELECT * FROM spirekeeper.lamassu_transactions;" \
|
||||
> lamassu_transactions_export_$(date +%Y%m%d_%H%M%S).csv
|
||||
|
||||
sqlite3 -header -csv /path/to/lnbits/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.dca_payments;" \
|
||||
"SELECT * FROM spirekeeper.dca_payments;" \
|
||||
> dca_payments_export_$(date +%Y%m%d_%H%M%S).csv
|
||||
|
||||
sqlite3 -header -csv /path/to/lnbits/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.dca_deposits;" \
|
||||
"SELECT * FROM spirekeeper.dca_deposits;" \
|
||||
> dca_deposits_export_$(date +%Y%m%d_%H%M%S).csv
|
||||
|
||||
sqlite3 -header -csv /path/to/lnbits/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.dca_clients;" \
|
||||
"SELECT * FROM spirekeeper.dca_clients;" \
|
||||
> dca_clients_export_$(date +%Y%m%d_%H%M%S).csv
|
||||
```
|
||||
|
||||
|
|
@ -946,9 +946,9 @@ SELECT
|
|||
dp.amount_sats as client_received,
|
||||
dp.status as payment_status,
|
||||
dp.payment_hash
|
||||
FROM satoshimachine.lamassu_transactions lt
|
||||
LEFT JOIN satoshimachine.dca_payments dp ON dp.lamassu_transaction_id = lt.id
|
||||
LEFT JOIN satoshimachine.dca_clients c ON dp.client_id = c.id
|
||||
FROM spirekeeper.lamassu_transactions lt
|
||||
LEFT JOIN spirekeeper.dca_payments dp ON dp.lamassu_transaction_id = lt.id
|
||||
LEFT JOIN spirekeeper.dca_clients c ON dp.client_id = c.id
|
||||
ORDER BY lt.created_at DESC, c.username;
|
||||
```
|
||||
|
||||
|
|
@ -981,18 +981,18 @@ async def process_lamassu_transaction(txn_data: dict) -> Optional[LamassuTransac
|
|||
|
||||
```sql
|
||||
-- Add unique constraint on transaction_id
|
||||
ALTER TABLE satoshimachine.lamassu_transactions
|
||||
ALTER TABLE spirekeeper.lamassu_transactions
|
||||
ADD CONSTRAINT unique_transaction_id UNIQUE (transaction_id);
|
||||
|
||||
-- Prevent negative balances
|
||||
ALTER TABLE satoshimachine.dca_clients
|
||||
ALTER TABLE spirekeeper.dca_clients
|
||||
ADD CONSTRAINT positive_balance CHECK (remaining_balance >= 0);
|
||||
|
||||
-- Ensure positive amounts
|
||||
ALTER TABLE satoshimachine.dca_deposits
|
||||
ALTER TABLE spirekeeper.dca_deposits
|
||||
ADD CONSTRAINT positive_deposit CHECK (amount > 0);
|
||||
|
||||
ALTER TABLE satoshimachine.dca_payments
|
||||
ALTER TABLE spirekeeper.dca_payments
|
||||
ADD CONSTRAINT positive_payment CHECK (amount_sats > 0);
|
||||
```
|
||||
|
||||
|
|
@ -1196,7 +1196,7 @@ grep "wallet.*api\|payment_hash" lnbits.log | tail -50
|
|||
### System Access
|
||||
|
||||
**LNBits Admin Dashboard**:
|
||||
- URL: `https://<your-lnbits-host>/satoshimachine`
|
||||
- URL: `https://<your-lnbits-host>/spirekeeper`
|
||||
- Requires superuser authentication
|
||||
|
||||
**Database Access**:
|
||||
|
|
@ -1205,7 +1205,7 @@ grep "wallet.*api\|payment_hash" lnbits.log | tail -50
|
|||
sqlite3 /home/padreug/AioLabs/Git/lnbits-extensions/lnbits/data/database.sqlite
|
||||
|
||||
# Direct table access
|
||||
sqlite3 /path/to/db "SELECT * FROM satoshimachine.<table_name>;"
|
||||
sqlite3 /path/to/db "SELECT * FROM spirekeeper.<table_name>;"
|
||||
```
|
||||
|
||||
**Log Files**:
|
||||
|
|
@ -1274,7 +1274,7 @@ pkill -f lnbits
|
|||
|
||||
```sql
|
||||
-- Disable automatic polling
|
||||
UPDATE satoshimachine.lamassu_config
|
||||
UPDATE spirekeeper.lamassu_config
|
||||
SET polling_enabled = false;
|
||||
```
|
||||
|
||||
|
|
@ -1283,7 +1283,7 @@ SET polling_enabled = false;
|
|||
```sql
|
||||
-- All client balances summary
|
||||
SELECT id, username, remaining_balance, created_at
|
||||
FROM satoshimachine.dca_clients
|
||||
FROM spirekeeper.dca_clients
|
||||
ORDER BY remaining_balance DESC;
|
||||
```
|
||||
|
||||
|
|
@ -1291,7 +1291,7 @@ ORDER BY remaining_balance DESC;
|
|||
|
||||
```sql
|
||||
SELECT id, transaction_id, created_at, crypto_atoms, base_amount, commission_amount
|
||||
FROM satoshimachine.lamassu_transactions
|
||||
FROM spirekeeper.lamassu_transactions
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 10;
|
||||
```
|
||||
|
|
@ -1299,7 +1299,7 @@ LIMIT 10;
|
|||
### Failed Payments
|
||||
|
||||
```sql
|
||||
SELECT * FROM satoshimachine.dca_payments
|
||||
SELECT * FROM spirekeeper.dca_payments
|
||||
WHERE status != 'completed'
|
||||
ORDER BY created_at DESC;
|
||||
```
|
||||
|
|
@ -1314,19 +1314,19 @@ BACKUP_DIR="emergency_backup_${DATE}"
|
|||
mkdir -p $BACKUP_DIR
|
||||
|
||||
sqlite3 -header -csv /path/to/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.lamassu_transactions;" \
|
||||
"SELECT * FROM spirekeeper.lamassu_transactions;" \
|
||||
> ${BACKUP_DIR}/lamassu_transactions.csv
|
||||
|
||||
sqlite3 -header -csv /path/to/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.dca_payments;" \
|
||||
"SELECT * FROM spirekeeper.dca_payments;" \
|
||||
> ${BACKUP_DIR}/dca_payments.csv
|
||||
|
||||
sqlite3 -header -csv /path/to/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.dca_deposits;" \
|
||||
"SELECT * FROM spirekeeper.dca_deposits;" \
|
||||
> ${BACKUP_DIR}/dca_deposits.csv
|
||||
|
||||
sqlite3 -header -csv /path/to/database.sqlite \
|
||||
"SELECT * FROM satoshimachine.dca_clients;" \
|
||||
"SELECT * FROM spirekeeper.dca_clients;" \
|
||||
> ${BACKUP_DIR}/dca_clients.csv
|
||||
|
||||
echo "Backup complete in ${BACKUP_DIR}/"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue