Balance Reconciliation System
This document describes the automatic balance reconciliation system that monitors for discrepancies between opportunity balances and blockchain deposits.
Overview
The system periodically checks all opportunity balances against confirmed blockchain deposits. When discrepancies are found, admins are notified through the admin notification system.
Background Job
Location
- Job script:
lib/jobs/checkBalanceDiscrepancies.ts - API trigger:
POST /api/admin/jobs/check-discrepancies
How It Works
- Fetches all opportunity balances with their confirmed deposits
- Calculates the sum of confirmed deposits for each balance
- Compares the sum against the
totalInvestedfield - Reports any discrepancies greater than $0.01 (accounting for floating point precision)
Cron Job Setup
To run the balance discrepancy check automatically, add this to your crontab:
# Run every hour
0 * * * * cd /var/www/opportunitydao && npx tsx lib/jobs/checkBalanceDiscrepancies.ts >> /var/log/reprise/balance-check.log 2>&1
# OR run every 6 hours
0 */6 * * * cd /var/www/opportunitydao && npx tsx lib/jobs/checkBalanceDiscrepancies.ts >> /var/log/reprise/balance-check.log 2>&1
# OR run daily at 3 AM
0 3 * * * cd /var/www/opportunitydao && npx tsx lib/jobs/checkBalanceDiscrepancies.ts >> /var/log/reprise/balance-check.log 2>&1
Note: Adjust the path to match your installation directory.
Using Systemd Timer (Alternative)
Create a systemd service and timer for more robust scheduling:
Service file: /etc/systemd/system/reprise-balance-check.service
[Unit]
Description=Reprise Balance Reconciliation Check
After=network.target
[Service]
Type=oneshot
User=www-data
WorkingDirectory=/var/www/opportunitydao
ExecStart=/usr/bin/npx tsx lib/jobs/checkBalanceDiscrepancies.ts
StandardOutput=journal
StandardError=journal
Timer file: /etc/systemd/system/reprise-balance-check.timer
[Unit]
Description=Run Reprise Balance Check Hourly
Requires=reprise-balance-check.service
[Timer]
OnCalendar=hourly
Persistent=true
[Install]
WantedBy=timers.target
Enable and start the timer:
sudo systemctl enable reprise-balance-check.timer
sudo systemctl start reprise-balance-check.timer
sudo systemctl status reprise-balance-check.timer
Admin Notifications
Notification System
The admin notification API (/api/admin/notifications) automatically includes:
pendingDeposits- Count of pending deposits requiring reviewbalanceDiscrepancies- Count of balances with discrepancieshasNotifications- True if either count is greater than 0
Polling Interval
AdminNav polls the notification endpoint every 30 seconds to check for:
- New pending deposits
- Balance discrepancies
Notification Display
When discrepancies are detected:
- Desktop: Red badge on user avatar with total notification count
- Mobile: Red badge on user avatar with total notification count
- Dropdown Menu: "Balance Discrepancies" link with count badge (both desktop and mobile)
- Direct Link: Takes admin to
/admin/reconcile-balances
Manual Reconciliation
Via UI
- Navigate to Tools → Reconcile Balances in admin panel
- Review discrepancies with detailed breakdown
- Select balances to fix (or use "Reconcile All")
- Confirm action to recalculate
totalInvestedfrom blockchain deposits
Via API
Check for discrepancies:
GET /api/admin/reconcile-balances
Reconcile specific balances:
POST /api/admin/reconcile-balances
Content-Type: application/json
{
"balanceIds": [1, 2, 3],
"mode": "recalculate"
}
Reconcile all discrepancies:
POST /api/admin/reconcile-balances
Content-Type: application/json
{
"mode": "recalculate"
}
Audit Trail
All reconciliation actions are logged to the audit_log table with:
- Action:
RECONCILE_BALANCE - Old values: Original
totalInvested,userId,opportunityId - New values: Corrected
totalInvested, user details, opportunity details, discrepancy amount, reconciled by admin email - IP address of admin performing the action
Source of Truth
The blockchain is always the source of truth. The system recalculates totalInvested based on the sum of confirmed blockchain deposits.
Integration with Deposit Processing
The balance check job works alongside the deposit processing job:
- Deposit Processing (
lib/jobs/processDeposits.ts) - Confirms pending deposits - Balance Check (
lib/jobs/checkBalanceDiscrepancies.ts) - Verifies balance accuracy
Recommended Schedule
# Process deposits every 3 minutes
*/3 * * * * cd /var/www/opportunitydao && npx tsx lib/jobs/processDeposits.ts >> /var/log/reprise/deposits.log 2>&1
# Check balances every hour
0 * * * * cd /var/www/opportunitydao && npx tsx lib/jobs/checkBalanceDiscrepancies.ts >> /var/log/reprise/balance-check.log 2>&1
Troubleshooting
No discrepancies showing but balances seem wrong
- Check if deposits are confirmed (status = 'confirmed')
- Verify the deposit processor is running
- Manually run the balance check job to see console output
- Check audit logs for recent reconciliation actions
Discrepancies not appearing in notifications
- Verify the admin notification polling is working (check browser console)
- Manually call
/api/admin/notificationsto check the response - Ensure discrepancies are greater than $0.01
- Check that the balance check job has run recently
How to run jobs manually
# Change to project directory
cd /var/www/opportunitydao
# Check for discrepancies
npx tsx lib/jobs/checkBalanceDiscrepancies.ts
# Process pending deposits
npx tsx lib/jobs/processDeposits.ts
# Via API (requires admin authentication)
curl -X POST http://localhost:3000/api/admin/jobs/check-discrepancies \
-H "Cookie: auth_token=YOUR_TOKEN"
curl -X POST http://localhost:3000/api/admin/jobs/process-deposits \
-H "Cookie: auth_token=YOUR_TOKEN"
Log Files
Recommended log file locations:
/var/log/reprise/balance-check.log- Balance discrepancy checks/var/log/reprise/deposits.log- Deposit processing/var/log/reprise/reconciliation.log- Manual reconciliations (via audit_log table)
Create log directory:
sudo mkdir -p /var/log/reprise
sudo chown www-data:www-data /var/log/reprise
Related Files
lib/jobs/checkBalanceDiscrepancies.ts- Main job scriptapp/api/admin/jobs/check-discrepancies/route.ts- API trigger endpointapp/api/admin/notifications/route.ts- Notification systemapp/api/admin/reconcile-balances/route.ts- Reconciliation APIapp/admin/reconcile-balances/page.tsx- Reconciliation UIcomponents/AdminNav.tsx- Notification displaylib/audit.ts- Audit logging