dubs-server 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +280 -0
- package/CLAUDE.md +46 -0
- package/CONNECT4_PRODUCTION_DEPLOY.md +155 -0
- package/CURRENT_SESSION.md +171 -0
- package/CURRENT_SESSION_DRAW.md +516 -0
- package/MARCH_MADNESS_SURVIVOR.md +254 -0
- package/PANDA.md +166 -0
- package/Procfile +4 -0
- package/README.md +476 -0
- package/controllers/livescoresController.js +376 -0
- package/controllers/pickemController.js +554 -0
- package/controllers/survivorAdminController.js +887 -0
- package/controllers/survivorController.js +623 -0
- package/cron/oracleMonitor.js +77 -0
- package/cron/pickemOracleMonitor.js +73 -0
- package/data/jackpot-history.json +952 -0
- package/data/ncaaTeams.js +406 -0
- package/documentation/API_SECURITY_GUIDE.md +327 -0
- package/documentation/ARCADE_API.md +593 -0
- package/documentation/ARCADE_IMPLEMENTATION_SUMMARY.md +399 -0
- package/documentation/ARCADE_QUICKSTART.md +242 -0
- package/documentation/AUTOMATIC_MODE_ORACLE.md +321 -0
- package/documentation/BUG_FIX_COHORT_DATE_DISPLAY.md +171 -0
- package/documentation/CLAIM_MIGRATION_INSTRUCTIONS.md +52 -0
- package/documentation/CLAIM_STATUS_FIX.md +67 -0
- package/documentation/CLI_TOOL_GUIDE.md +372 -0
- package/documentation/COHORT_RETENTION_ANALYSIS.md +295 -0
- package/documentation/COHORT_RETENTION_IMPLEMENTATION_COMPLETE.md +461 -0
- package/documentation/COHORT_RETENTION_SUMMARY.md +204 -0
- package/documentation/COMPLETE_PROJECT_SUMMARY.md +490 -0
- package/documentation/DATABASE_QUERIES.md +269 -0
- package/documentation/DATABASE_RETENTION_POLICY.md +390 -0
- package/documentation/DATABASE_SETUP_GUIDE.md +361 -0
- package/documentation/DATABASE_SETUP_SUMMARY.md +247 -0
- package/documentation/DEMO_API_CURL_COMMANDS.md +656 -0
- package/documentation/DEPLOYMENT_SUMMARY.txt +100 -0
- package/documentation/DUPLICATE_NOTIFICATIONS_FIXED.md +201 -0
- package/documentation/EXCHANGE_RATES_INTEGRATION.md +371 -0
- package/documentation/FINAL_API_PROTECTION_TABLE.md +175 -0
- package/documentation/GAME_START_NOTIFICATIONS_DEPLOYMENT.md +256 -0
- package/documentation/GAME_START_NOTIFICATIONS_INTEGRATION.md +275 -0
- package/documentation/HEROKU_DEPLOYMENT.md +134 -0
- package/documentation/HEROKU_SCHEDULER_SETUP.md +271 -0
- package/documentation/JACKPOT_API.md +521 -0
- package/documentation/JACKPOT_DEPLOYMENT_GUIDE.md +362 -0
- package/documentation/JWT_IMPLEMENTATION_SUMMARY.md +373 -0
- package/documentation/JWT_QUICK_SETUP.md +268 -0
- package/documentation/JWT_TESTING_GUIDE.md +404 -0
- package/documentation/KEEPER_RECOVERY_GUIDE.md +381 -0
- package/documentation/KEEPER_SETUP.md +206 -0
- package/documentation/KEEPER_STATE_MACHINE.md +423 -0
- package/documentation/LATEST_PRODUCTION_SETUP.md +387 -0
- package/documentation/LOCAL_VOTING_TEST.md +279 -0
- package/documentation/ORACLE_FIXES_SUMMARY.md +188 -0
- package/documentation/ORACLE_POSTGRESQL_UPDATE.md +202 -0
- package/documentation/PAYMENT_DEPLOYMENT.md +209 -0
- package/documentation/PNL_TRACKING_SETUP.md +189 -0
- package/documentation/PREVENTING_LOCKUP_ERRORS.md +472 -0
- package/documentation/PRODUCTION_READY_SUMMARY.md +227 -0
- package/documentation/PUBLIC_VS_PRIVATE_ENDPOINTS.md +278 -0
- package/documentation/QUICK_AUTH_SETUP.md +99 -0
- package/documentation/QUICK_DEPLOY.md +224 -0
- package/documentation/QUICK_FIX.md +114 -0
- package/documentation/QUICK_START.md +152 -0
- package/documentation/REFEREE_MODE_GUIDE.md +392 -0
- package/documentation/RETENTION_CORE_ACTION_UPDATE.md +313 -0
- package/documentation/RETENTION_UPDATE_SUMMARY.md +108 -0
- package/documentation/RUN_MIGRATION_NOW.md +39 -0
- package/documentation/SCRIPTS_UPDATE_SUMMARY.md +251 -0
- package/documentation/SETUP_GUIDE.md +184 -0
- package/documentation/STATE_MACHINE_IMPLEMENTATION.md +250 -0
- package/documentation/TELEGRAM_NOTIFICATIONS_DIAGNOSIS.md +361 -0
- package/documentation/UNIFIED_ARCHITECTURE.md +231 -0
- package/documentation/VOTING_DEPLOYMENT_SUMMARY.md +392 -0
- package/documentation/WEBSOCKET_ARCHITECTURE.md +881 -0
- package/documentation/WHAT_WE_BUILT_TODAY.md +369 -0
- package/documentation/latest/LATEST_PRODUCTION_SETUP.md +865 -0
- package/ecosystem.config.js +65 -0
- package/env.template +125 -0
- package/middleware/apiKeyAuth.js +136 -0
- package/middleware/authenticate.js +214 -0
- package/middleware/developerUserAuth.js +76 -0
- package/middleware/socketAuth.js +69 -0
- package/package.json +49 -0
- package/postman/Dubs-API-v1-With-Voting.postman_collection.json +555 -0
- package/postman/Dubs-API-v1.postman_collection.json +205 -0
- package/postman/Dubs_Developer_API.postman_collection.json +662 -0
- package/postman/QUICKSTART.md +118 -0
- package/postman/QUICK_REFERENCE.md +246 -0
- package/postman/README.md +71 -0
- package/postman/VOTING_API_GUIDE.md +426 -0
- package/refactor/Animations.md +148 -0
- package/refactor/Chat.md +252 -0
- package/routes/actionsRoutes.js +699 -0
- package/routes/adminRoutes.js +370 -0
- package/routes/analyticsRoutes.js +1262 -0
- package/routes/arcadeRoutes.js +557 -0
- package/routes/authRoutes.js +2310 -0
- package/routes/avatarRoutes.js +85 -0
- package/routes/botRoutes.js +211 -0
- package/routes/chatRoutes.js +377 -0
- package/routes/cryptoPriceRoutes.js +105 -0
- package/routes/developerRoutes.js +4201 -0
- package/routes/deviceRoutes.js +214 -0
- package/routes/dmRoutes.js +167 -0
- package/routes/esportsRoutes.js +806 -0
- package/routes/exchangeRateRoutes.js +233 -0
- package/routes/gamesRoutes.js +3028 -0
- package/routes/jackpotRoutes.js +754 -0
- package/routes/keeperMonitoringRoutes.js +156 -0
- package/routes/keeperWebhookRoutes.js +466 -0
- package/routes/livescoresRoutes.js +31 -0
- package/routes/pickemAdminRoutes.js +199 -0
- package/routes/pickemRoutes.js +231 -0
- package/routes/playerStatsRoutes.js +147 -0
- package/routes/portfolioRoutes.js +217 -0
- package/routes/promoRoutes.js +418 -0
- package/routes/referralEarningsRoutes.js +392 -0
- package/routes/socialRoutes.js +459 -0
- package/routes/sportsRoutes.js +1271 -0
- package/routes/survivorAdminRoutes.js +345 -0
- package/routes/survivorRoutes.js +756 -0
- package/routes/uploadRoutes.js +256 -0
- package/routes/userProfileRoutes.js +244 -0
- package/routes/whatsNewRoutes.js +331 -0
- package/scripts/.claude/settings.local.json +15 -0
- package/scripts/README.md +170 -0
- package/scripts/RESTART_EVERYTHING.sh +104 -0
- package/scripts/add-claim-columns.sql +48 -0
- package/scripts/add-crypto-prices-cache.sql +27 -0
- package/scripts/add-exchange-rates-cache.sql +40 -0
- package/scripts/add-game-invite-column.sql +23 -0
- package/scripts/add-game-invite-notification.sql +33 -0
- package/scripts/add-game-invite-telegram-pref.sql +16 -0
- package/scripts/add-game-joined-notification.sql +16 -0
- package/scripts/add-game-joined-pref.js +40 -0
- package/scripts/add-game-joined-preference.sql +6 -0
- package/scripts/add-game-start-notifications.sql +41 -0
- package/scripts/add-notification-flags-to-games.sql +55 -0
- package/scripts/add-pending-game-dismissals.sql +19 -0
- package/scripts/add-preferred-currency.sql +34 -0
- package/scripts/add-winner-columns.js +61 -0
- package/scripts/add_mention_system.sql +53 -0
- package/scripts/add_payment_system.sql +96 -0
- package/scripts/add_sports_event_id_column.sql +22 -0
- package/scripts/analyze-cohort-data-heroku.js +276 -0
- package/scripts/analyze-cohort-data.js +295 -0
- package/scripts/analyze-prod-cohorts.sh +10 -0
- package/scripts/backfill-matchup-images.js +245 -0
- package/scripts/backfill-missing-signatures.js +175 -0
- package/scripts/backfill-referral-earnings.js +202 -0
- package/scripts/check-chat-schema.js +130 -0
- package/scripts/check-db.sh +14 -0
- package/scripts/check_oracle_in_game.js +54 -0
- package/scripts/cleanup-database.js +193 -0
- package/scripts/clear-notification-cache.js +85 -0
- package/scripts/convert-mnemonic.js +50 -0
- package/scripts/create-users-table.sql +44 -0
- package/scripts/debug-cohort-counts.js +248 -0
- package/scripts/debug-winner-calc.js +84 -0
- package/scripts/deploy-payment-system.sh +118 -0
- package/scripts/deploy-to-heroku.sh +63 -0
- package/scripts/diagnose-locked-round.js +143 -0
- package/scripts/dubs-cli.js +720 -0
- package/scripts/dump-account.js +65 -0
- package/scripts/find-vrf-offset.js +48 -0
- package/scripts/fix-chat-notifications-constraint.sql +122 -0
- package/scripts/fix-claim-columns.js +124 -0
- package/scripts/fix-constraint-now.js +44 -0
- package/scripts/fix-lock-timestamps.js +96 -0
- package/scripts/fix-locked-round.sh +126 -0
- package/scripts/fix-missing-badges.sql +91 -0
- package/scripts/fix-payment-notifications.sql +41 -0
- package/scripts/force-new-round.js +55 -0
- package/scripts/force-resolve-and-claim.js +278 -0
- package/scripts/important/README.md +115 -0
- package/scripts/important/authority-force-lock.js +197 -0
- package/scripts/important/authority-resolve-game.js +267 -0
- package/scripts/important/check-game-status.js +373 -0
- package/scripts/important/list-pending-games-by-version.js +270 -0
- package/scripts/important/reconcile-v1-v2-payouts.js +270 -0
- package/scripts/initialize-jackpot.js +111 -0
- package/scripts/jackpot/.claude/settings.local.json +10 -0
- package/scripts/jackpot/force-reset.js +84 -0
- package/scripts/jackpot/initialize-mainnet.js +100 -0
- package/scripts/jackpot/keeper.js +742 -0
- package/scripts/jackpot/status.js +107 -0
- package/scripts/jackpot/update-round-duration.js +143 -0
- package/scripts/keeper-bot.js +112 -0
- package/scripts/list-pending-games.js +131 -0
- package/scripts/migrate-chat-v2.js +127 -0
- package/scripts/migrate-chat-winners.js +84 -0
- package/scripts/migrate-chat.sh +17 -0
- package/scripts/migrate-game-invite.js +83 -0
- package/scripts/migrate-heroku-game-notifications.sh +159 -0
- package/scripts/migrations/001_analytics_tables.sql +422 -0
- package/scripts/migrations/002_add_matchup_image_url.sql +14 -0
- package/scripts/migrations/003_referral_earnings.sql +208 -0
- package/scripts/migrations/004_add_whats_new_notification_type.sql +62 -0
- package/scripts/migrations/005_add_connect4_your_turn_notification.sql +61 -0
- package/scripts/migrations/005_push_notifications.sql +55 -0
- package/scripts/migrations/006_add_draw_team_players.sql +28 -0
- package/scripts/migrations/006_add_game_cancelled_notification.sql +62 -0
- package/scripts/migrations/007_add_gif_url.sql +8 -0
- package/scripts/migrations/008_add_connect4_columns.sql +139 -0
- package/scripts/migrations/008_add_pool_tracking.sql +22 -0
- package/scripts/migrations/009_create_survivor_pool_tables.sql +174 -0
- package/scripts/migrations/010_add_survivor_pool_outcome.sql +28 -0
- package/scripts/migrations/011_create_developer_tables.sql +67 -0
- package/scripts/migrations/011_fix_keeper_tables.sql +85 -0
- package/scripts/migrations/012_create_developer_webhooks.sql +31 -0
- package/scripts/migrations/013_add_network_mode.sql +18 -0
- package/scripts/migrations/014_create_developer_app_users.sql +19 -0
- package/scripts/migrations/015_add_ui_config.sql +4 -0
- package/scripts/migrations/016_add_resolution_secret.sql +4 -0
- package/scripts/migrations/017_add_external_game_id.sql +3 -0
- package/scripts/migrations/018_create_pickem_tables.sql +115 -0
- package/scripts/migrations/019_expo_push_tokens.sql +19 -0
- package/scripts/migrations/create_whats_new_tables.sql +88 -0
- package/scripts/migrations/drop_live_games_tables.sql +34 -0
- package/scripts/open-jackpot-round.js +85 -0
- package/scripts/purge-all-data.sh +329 -0
- package/scripts/purge-all-data.sql +142 -0
- package/scripts/purge-heroku-data.sh +149 -0
- package/scripts/purge-heroku-data.sql +62 -0
- package/scripts/rebuild-heroku-database.sh +113 -0
- package/scripts/recover-funds.js +357 -0
- package/scripts/regenerate-epl-images.js +278 -0
- package/scripts/resize-s3-matchup-images.js +374 -0
- package/scripts/resolve-direct.js +88 -0
- package/scripts/resolve-mock-game.js +124 -0
- package/scripts/resolve-pickem-game.js +55 -0
- package/scripts/resolve-round-manual.js +83 -0
- package/scripts/resolve-stuck-game.js +382 -0
- package/scripts/resolve-stuck-round.js +42 -0
- package/scripts/run-connect4-migration.sh +16 -0
- package/scripts/run-mention-migration.sh +32 -0
- package/scripts/run-payment-migration.sh +51 -0
- package/scripts/run-preferred-currency-migration.sh +31 -0
- package/scripts/run-referral-earnings-migration.sh +32 -0
- package/scripts/run-survivor-outcome-migration.sh +16 -0
- package/scripts/seed-test-users.js +346 -0
- package/scripts/setup-auth-tables.js +78 -0
- package/scripts/setup-complete-database.sql +992 -0
- package/scripts/setup-database-fresh.sh +359 -0
- package/scripts/setup-heroku-keeper.sh +48 -0
- package/scripts/setup-keeper-database.js +83 -0
- package/scripts/setup-keeper-state-db.sql +110 -0
- package/scripts/setup-oracle.sh +39 -0
- package/scripts/setup-pnl-tracking.js +111 -0
- package/scripts/start-devnet.sh +14 -0
- package/scripts/test-arcade-devnet.sh +160 -0
- package/scripts/test-arcade-match.sh +109 -0
- package/scripts/test-automatic-mode.sh +239 -0
- package/scripts/test-connect4-cancel-claim.js +370 -0
- package/scripts/test-connect4-e2e.js +369 -0
- package/scripts/test-connect4-resolve.js +369 -0
- package/scripts/test-game-state-endpoint.js +136 -0
- package/scripts/test-invite-notification.js +86 -0
- package/scripts/test-jackpot-api.sh +71 -0
- package/scripts/test-poll-confirmation.js +267 -0
- package/scripts/test-resolve-game.js +271 -0
- package/scripts/test-resolve-signature.js +223 -0
- package/scripts/test-signature-preservation.js +124 -0
- package/scripts/test-state-machine.js +291 -0
- package/scripts/test-webhook-receiver.js +60 -0
- package/scripts/update-notification-constraint.js +52 -0
- package/scripts/verify-account-layout.js +145 -0
- package/scripts/verify-winner-algorithm.js +278 -0
- package/server.js +5259 -0
- package/services/arcadeMatchService.js +763 -0
- package/services/automaticGameOracle.js +1596 -0
- package/services/chatService.js +1612 -0
- package/services/connect4GameService.js +1049 -0
- package/services/connect4NotificationService.js +374 -0
- package/services/cryptoPriceService.js +223 -0
- package/services/customGameResolver.js +260 -0
- package/services/db.js +79 -0
- package/services/directMessageService.js +389 -0
- package/services/discordNotifications.js +160 -0
- package/services/exchangeRateService.js +289 -0
- package/services/expoPushService.js +314 -0
- package/services/gamesCacheService.js +539 -0
- package/services/jackpotHistory.js +331 -0
- package/services/jackpotService.js +856 -0
- package/services/keeperStateService.js +355 -0
- package/services/matchupImageService.js +591 -0
- package/services/notificationCacheService.js +407 -0
- package/services/pickemOracle.js +440 -0
- package/services/playerStatsService.js +389 -0
- package/services/portfolioService.js +555 -0
- package/services/promoService.js +757 -0
- package/services/promoTreasuryService.js +239 -0
- package/services/pushNotifications.js +353 -0
- package/services/redisService.js +422 -0
- package/services/referralEarningsService.js +728 -0
- package/services/s3Service.js +396 -0
- package/services/socialService.js +1202 -0
- package/services/survivorOracle.js +469 -0
- package/services/survivorSimulator.js +475 -0
- package/services/telegramNotifications.js +461 -0
- package/services/userProfileStatsService.js +1185 -0
- package/services/whatsNewService.js +388 -0
- package/utils/urlHelper.js +95 -0
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
# 🔄 Keeper Recovery Guide
|
|
2
|
+
|
|
3
|
+
**Last Updated:** November 17, 2025
|
|
4
|
+
**System:** Dubs Jackpot Keeper with State Machine
|
|
5
|
+
**Status:** ✅ Production Ready with Auto-Recovery
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🎯 TL;DR - Quick Recovery
|
|
10
|
+
|
|
11
|
+
**Keeper stopped working?**
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# 99% of the time, just restart it:
|
|
15
|
+
heroku ps:restart jackpot-keeper -a dubs-server-dev
|
|
16
|
+
|
|
17
|
+
# Watch it auto-recover:
|
|
18
|
+
heroku logs --tail -a dubs-server-dev --dyno=jackpot-keeper
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**That's it!** The state machine handles the rest automatically.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 🔍 How Auto-Recovery Works
|
|
26
|
+
|
|
27
|
+
### **On Every Keeper Startup:**
|
|
28
|
+
|
|
29
|
+
```javascript
|
|
30
|
+
🚀 Keeper bot started!
|
|
31
|
+
|
|
32
|
+
🔧 Checking for stuck rounds...
|
|
33
|
+
✅ No stuck rounds found
|
|
34
|
+
|
|
35
|
+
// If stuck rounds exist:
|
|
36
|
+
⚠️ Found 1 stuck round(s)!
|
|
37
|
+
🔧 Recovering round 555 stuck in 'locked' for 127s
|
|
38
|
+
On-chain status: Locked, DB status: locked
|
|
39
|
+
Retrying reveal...
|
|
40
|
+
✅ Randomness revealed!
|
|
41
|
+
💰 Resolving round 555...
|
|
42
|
+
🏆 Round 555 resolved!
|
|
43
|
+
✅ Recovery complete
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### **What It Checks:**
|
|
47
|
+
|
|
48
|
+
1. **Database query:** Find rounds stuck in incomplete states
|
|
49
|
+
2. **Time check:** Find rounds not updated in 5+ minutes
|
|
50
|
+
3. **On-chain verification:** Compare DB state vs blockchain
|
|
51
|
+
4. **Smart resume:** Continue from exact step where it stopped
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 📋 Common Scenarios & Solutions
|
|
56
|
+
|
|
57
|
+
### **Scenario 1: Keeper Crashed During Lock**
|
|
58
|
+
|
|
59
|
+
**Symptoms:**
|
|
60
|
+
- Round shows "Open" on-chain
|
|
61
|
+
- Database shows "locking" status
|
|
62
|
+
- No activity for 5+ minutes
|
|
63
|
+
|
|
64
|
+
**Solution:**
|
|
65
|
+
```bash
|
|
66
|
+
# Just restart
|
|
67
|
+
heroku ps:restart jackpot-keeper -a dubs-server-dev
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**What Happens:**
|
|
71
|
+
- Keeper detects round in "locking" state
|
|
72
|
+
- Checks on-chain: still "Open"
|
|
73
|
+
- Retries lock transaction
|
|
74
|
+
- Continues to reveal → resolve → reset
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
### **Scenario 2: Keeper Crashed During Reveal**
|
|
79
|
+
|
|
80
|
+
**Symptoms:**
|
|
81
|
+
- Round shows "Locked" on-chain
|
|
82
|
+
- Database shows "locked" or "revealing"
|
|
83
|
+
- VRF not yet revealed
|
|
84
|
+
|
|
85
|
+
**Solution:**
|
|
86
|
+
```bash
|
|
87
|
+
# Just restart
|
|
88
|
+
heroku ps:restart jackpot-keeper -a dubs-server-dev
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**What Happens:**
|
|
92
|
+
- Keeper sees round is "locked"
|
|
93
|
+
- Skips lock step (already done)
|
|
94
|
+
- Calls reveal with new oracle seed
|
|
95
|
+
- Continues to resolve → reset
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
### **Scenario 3: Keeper Crashed During Resolve**
|
|
100
|
+
|
|
101
|
+
**Symptoms:**
|
|
102
|
+
- Round shows "Locked" on-chain
|
|
103
|
+
- VRF is revealed
|
|
104
|
+
- Winner not yet paid
|
|
105
|
+
|
|
106
|
+
**Solution:**
|
|
107
|
+
```bash
|
|
108
|
+
# Just restart
|
|
109
|
+
heroku ps:restart jackpot-keeper -a dubs-server-dev
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**What Happens:**
|
|
113
|
+
- Keeper sees round is "locked" with VRF
|
|
114
|
+
- Skips lock and reveal (already done)
|
|
115
|
+
- Calls resolve to pay winner
|
|
116
|
+
- Resets for next round
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
### **Scenario 4: Keeper is Running but Not Processing**
|
|
121
|
+
|
|
122
|
+
**Check if it's actually stuck:**
|
|
123
|
+
```bash
|
|
124
|
+
# 1. Check for stuck rounds
|
|
125
|
+
curl https://dubs-server-dev-55d1fba09a97.herokuapp.com/api/keeper/rounds/stuck
|
|
126
|
+
|
|
127
|
+
# 2. Check keeper health
|
|
128
|
+
curl https://dubs-server-dev-55d1fba09a97.herokuapp.com/api/keeper/health
|
|
129
|
+
|
|
130
|
+
# 3. Check logs
|
|
131
|
+
heroku logs --tail -a dubs-server-dev --dyno=jackpot-keeper
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**If stuck rounds found:**
|
|
135
|
+
```bash
|
|
136
|
+
# Restart to trigger recovery
|
|
137
|
+
heroku ps:restart jackpot-keeper -a dubs-server-dev
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
### **Scenario 5: Database Shows Stuck Round, On-Chain Says Open**
|
|
143
|
+
|
|
144
|
+
**This means round completed but DB didn't update**
|
|
145
|
+
|
|
146
|
+
**Solution:**
|
|
147
|
+
```bash
|
|
148
|
+
# Manually mark as resolved
|
|
149
|
+
heroku pg:psql -a dubs-server-dev -c "
|
|
150
|
+
UPDATE keeper_rounds
|
|
151
|
+
SET status = 'resolved', resolved_at = NOW()
|
|
152
|
+
WHERE round_id = 555;
|
|
153
|
+
"
|
|
154
|
+
|
|
155
|
+
# Restart keeper
|
|
156
|
+
heroku ps:restart jackpot-keeper -a dubs-server-dev
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 🚨 Emergency Recovery (Nuclear Option)
|
|
162
|
+
|
|
163
|
+
**If keeper is completely broken and won't recover:**
|
|
164
|
+
|
|
165
|
+
### **Step 1: Stop Keeper**
|
|
166
|
+
```bash
|
|
167
|
+
heroku ps:scale jackpot-keeper=0 -a dubs-server-dev
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### **Step 2: Check On-Chain State**
|
|
171
|
+
```bash
|
|
172
|
+
curl https://dubs-server-dev-55d1fba09a97.herokuapp.com/jackpot/round/current
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### **Step 3: Clean Database**
|
|
176
|
+
```bash
|
|
177
|
+
# Mark all incomplete rounds as resolved
|
|
178
|
+
heroku pg:psql -a dubs-server-dev -c "
|
|
179
|
+
UPDATE keeper_rounds
|
|
180
|
+
SET status = 'resolved', resolved_at = NOW()
|
|
181
|
+
WHERE status NOT IN ('resolved', 'open');
|
|
182
|
+
"
|
|
183
|
+
|
|
184
|
+
# Check what's in DB now
|
|
185
|
+
heroku pg:psql -a dubs-server-dev -c "
|
|
186
|
+
SELECT round_id, status FROM keeper_rounds
|
|
187
|
+
WHERE status != 'resolved'
|
|
188
|
+
ORDER BY round_id DESC;
|
|
189
|
+
"
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### **Step 4: Restart Keeper**
|
|
193
|
+
```bash
|
|
194
|
+
heroku ps:scale jackpot-keeper=1 -a dubs-server-dev
|
|
195
|
+
heroku logs --tail -a dubs-server-dev --dyno=jackpot-keeper
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## 📊 Monitoring Commands
|
|
201
|
+
|
|
202
|
+
### **Check if Keeper is Alive:**
|
|
203
|
+
```bash
|
|
204
|
+
# Method 1: Check Heroku process
|
|
205
|
+
heroku ps -a dubs-server-dev | grep jackpot-keeper
|
|
206
|
+
|
|
207
|
+
# Method 2: Check API
|
|
208
|
+
curl https://dubs-server-dev-55d1fba09a97.herokuapp.com/api/keeper/health
|
|
209
|
+
|
|
210
|
+
# Method 3: Check logs (should see activity every 5 seconds)
|
|
211
|
+
heroku logs --tail -a dubs-server-dev --dyno=jackpot-keeper -n 10
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### **Check for Problems:**
|
|
215
|
+
```bash
|
|
216
|
+
# Stuck rounds?
|
|
217
|
+
curl https://dubs-server-dev-55d1fba09a97.herokuapp.com/api/keeper/rounds/stuck
|
|
218
|
+
|
|
219
|
+
# Recent failures?
|
|
220
|
+
heroku pg:psql -a dubs-server-dev -c "
|
|
221
|
+
SELECT action, success, error_message, timestamp
|
|
222
|
+
FROM keeper_actions
|
|
223
|
+
WHERE success = false
|
|
224
|
+
ORDER BY timestamp DESC
|
|
225
|
+
LIMIT 10;
|
|
226
|
+
"
|
|
227
|
+
|
|
228
|
+
# High retry counts?
|
|
229
|
+
heroku pg:psql -a dubs-server-dev -c "
|
|
230
|
+
SELECT round_id, status, retry_count, last_error
|
|
231
|
+
FROM keeper_rounds
|
|
232
|
+
WHERE retry_count > 0
|
|
233
|
+
ORDER BY round_id DESC
|
|
234
|
+
LIMIT 10;
|
|
235
|
+
"
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## 🔧 Troubleshooting Checklist
|
|
241
|
+
|
|
242
|
+
**Keeper won't start:**
|
|
243
|
+
- [ ] Check Heroku dyno is running: `heroku ps -a dubs-server-dev`
|
|
244
|
+
- [ ] Check DATABASE_URL is set: `heroku config:get DATABASE_URL -a dubs-server-dev`
|
|
245
|
+
- [ ] Check KEEPER_PRIVATE_KEY is set: `heroku config:get KEEPER_PRIVATE_KEY -a dubs-server-dev`
|
|
246
|
+
- [ ] Check logs for errors: `heroku logs --tail -a dubs-server-dev --dyno=jackpot-keeper`
|
|
247
|
+
|
|
248
|
+
**Keeper running but not processing:**
|
|
249
|
+
- [ ] Check current round: `curl https://dubs-server-dev-55d1fba09a97.herokuapp.com/jackpot/round/current`
|
|
250
|
+
- [ ] Check stuck rounds: `curl https://dubs-server-dev-55d1fba09a97.herokuapp.com/api/keeper/rounds/stuck`
|
|
251
|
+
- [ ] Restart keeper: `heroku ps:restart jackpot-keeper -a dubs-server-dev`
|
|
252
|
+
|
|
253
|
+
**Round stuck for hours:**
|
|
254
|
+
- [ ] Check database state vs on-chain state
|
|
255
|
+
- [ ] Manually mark as resolved (see Scenario 5 above)
|
|
256
|
+
- [ ] Restart keeper
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## 💊 Health Check Script
|
|
261
|
+
|
|
262
|
+
**Save this as `check-keeper.sh`:**
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
#!/bin/bash
|
|
266
|
+
|
|
267
|
+
echo "🔍 KEEPER HEALTH CHECK"
|
|
268
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
269
|
+
|
|
270
|
+
# Check if keeper dyno is running
|
|
271
|
+
echo "📊 Dyno Status:"
|
|
272
|
+
heroku ps -a dubs-server-dev | grep jackpot-keeper
|
|
273
|
+
|
|
274
|
+
# Check API health
|
|
275
|
+
echo -e "\n💊 API Health:"
|
|
276
|
+
HEALTH=$(curl -s https://dubs-server-dev-55d1fba09a97.herokuapp.com/api/keeper/health)
|
|
277
|
+
echo $HEALTH | jq '{healthy, stuckRounds: .stuckRounds | length, resolved: .summary.resolved_rounds}'
|
|
278
|
+
|
|
279
|
+
# Check for stuck rounds
|
|
280
|
+
STUCK=$(echo $HEALTH | jq -r '.stuckRounds | length')
|
|
281
|
+
if [ "$STUCK" != "0" ]; then
|
|
282
|
+
echo "⚠️ WARNING: $STUCK stuck round(s) detected!"
|
|
283
|
+
echo " Action: heroku ps:restart jackpot-keeper -a dubs-server-dev"
|
|
284
|
+
else
|
|
285
|
+
echo "✅ No stuck rounds"
|
|
286
|
+
fi
|
|
287
|
+
|
|
288
|
+
# Check recent activity
|
|
289
|
+
echo -e "\n📝 Recent Activity:"
|
|
290
|
+
heroku logs -a dubs-server-dev --dyno=jackpot-keeper -n 3 | grep -E "(Round|✅|❌)"
|
|
291
|
+
|
|
292
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**Run it:**
|
|
296
|
+
```bash
|
|
297
|
+
chmod +x check-keeper.sh
|
|
298
|
+
./check-keeper.sh
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## 🎯 Performance Metrics
|
|
304
|
+
|
|
305
|
+
**Check how well the keeper is performing:**
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
heroku pg:psql -a dubs-server-dev -c "
|
|
309
|
+
SELECT
|
|
310
|
+
action,
|
|
311
|
+
COUNT(*) as total,
|
|
312
|
+
SUM(CASE WHEN success THEN 1 ELSE 0 END) as successes,
|
|
313
|
+
ROUND(100.0 * SUM(CASE WHEN success THEN 1 ELSE 0 END) / COUNT(*), 1) as success_rate,
|
|
314
|
+
ROUND(AVG(duration_ms)) as avg_ms,
|
|
315
|
+
MAX(duration_ms) as max_ms
|
|
316
|
+
FROM keeper_actions
|
|
317
|
+
GROUP BY action
|
|
318
|
+
ORDER BY action;
|
|
319
|
+
"
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Expected output:**
|
|
323
|
+
```
|
|
324
|
+
action | total | successes | success_rate | avg_ms | max_ms
|
|
325
|
+
---------|-------|-----------|--------------|--------|--------
|
|
326
|
+
lock | 10 | 10 | 100.0 | 1352 | 2000
|
|
327
|
+
reset | 40 | 40 | 100.0 | 1255 | 2100
|
|
328
|
+
resolve | 10 | 10 | 100.0 | 1740 | 2500
|
|
329
|
+
reveal | 10 | 10 | 100.0 | 966 | 1500
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**Good:** 95%+ success rate, <3s average
|
|
333
|
+
**Concerning:** <90% success rate, >5s average → investigate
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## 📞 When to Ask for Help
|
|
338
|
+
|
|
339
|
+
**Auto-recovery should handle:**
|
|
340
|
+
- ✅ Keeper crashes
|
|
341
|
+
- ✅ Network timeouts
|
|
342
|
+
- ✅ Single transaction failures
|
|
343
|
+
- ✅ Heroku dyno restarts
|
|
344
|
+
|
|
345
|
+
**You need manual intervention if:**
|
|
346
|
+
- ❌ Same round stuck for 30+ minutes after restart
|
|
347
|
+
- ❌ Success rate drops below 80%
|
|
348
|
+
- ❌ Database shows many retries (retry_count > 5)
|
|
349
|
+
- ❌ On-chain state and DB state are completely mismatched
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## 🎉 The Power of State Machine
|
|
354
|
+
|
|
355
|
+
**Before State Machine:**
|
|
356
|
+
- Keeper crash = manual recovery needed
|
|
357
|
+
- No visibility into what failed
|
|
358
|
+
- Lost track of progress
|
|
359
|
+
- Had to debug from logs
|
|
360
|
+
|
|
361
|
+
**With State Machine:**
|
|
362
|
+
- Keeper crash = automatic recovery
|
|
363
|
+
- Complete visibility in database
|
|
364
|
+
- Never loses progress
|
|
365
|
+
- Easy debugging with SQL queries
|
|
366
|
+
|
|
367
|
+
**Recovery went from "panic and debug for 2 hours" to "restart and it fixes itself in 10 seconds"**
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## 📚 Additional Resources
|
|
372
|
+
|
|
373
|
+
- Database Queries: See `DATABASE_QUERIES.md`
|
|
374
|
+
- State Machine Guide: See `KEEPER_STATE_MACHINE.md`
|
|
375
|
+
- Implementation Details: See `STATE_MACHINE_IMPLEMENTATION.md`
|
|
376
|
+
- Monitoring API: `https://dubs-server-dev-55d1fba09a97.herokuapp.com/api/keeper/*`
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
**Your keeper is bulletproof. It will auto-recover from 99% of failures.** 🛡️
|
|
381
|
+
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# 🤖 Keeper Bot Setup for Heroku
|
|
2
|
+
|
|
3
|
+
## The Problem
|
|
4
|
+
|
|
5
|
+
The keeper bot needs a wallet to sign transactions, but wallet files in `wallets/` directory are ignored by git and won't be deployed to Heroku.
|
|
6
|
+
|
|
7
|
+
## The Solution
|
|
8
|
+
|
|
9
|
+
We use an environment variable `KEEPER_PRIVATE_KEY` to securely pass the wallet's private key to Heroku.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Quick Setup (Automated)
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
cd /Users/adamdahan/Developer/iheartsolana/solana-programs/dubs-server
|
|
17
|
+
|
|
18
|
+
# Run the setup script
|
|
19
|
+
./setup-heroku-keeper.sh
|
|
20
|
+
|
|
21
|
+
# That's it! The script will:
|
|
22
|
+
# 1. Read wallets/jackpot_oracle.json
|
|
23
|
+
# 2. Set KEEPER_PRIVATE_KEY on Heroku
|
|
24
|
+
# 3. Show you the wallet address
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Manual Setup
|
|
30
|
+
|
|
31
|
+
If you prefer to do it manually:
|
|
32
|
+
|
|
33
|
+
### Step 1: Get the Private Key
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
cd /Users/adamdahan/Developer/iheartsolana/solana-programs/dubs-server
|
|
37
|
+
|
|
38
|
+
# View the wallet (it's a JSON array)
|
|
39
|
+
cat wallets/jackpot_oracle.json
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
You'll see something like:
|
|
43
|
+
```json
|
|
44
|
+
[135,155,140,135,170,89,66,124,...]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Step 2: Set on Heroku
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Set the environment variable (paste the entire JSON array)
|
|
51
|
+
heroku config:set KEEPER_PRIVATE_KEY='[135,155,140,135,170,89,66,124,...]' -a dubs-server-dev
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Important:** Keep the single quotes around the JSON array!
|
|
55
|
+
|
|
56
|
+
### Step 3: Verify
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Check it's set (will show first few characters)
|
|
60
|
+
heroku config:get KEEPER_PRIVATE_KEY -a dubs-server-dev
|
|
61
|
+
|
|
62
|
+
# Deploy and test
|
|
63
|
+
git push heroku-dev main
|
|
64
|
+
heroku ps:scale jackpot-keeper=1 -a dubs-server-dev
|
|
65
|
+
heroku logs --tail --ps jackpot-keeper -a dubs-server-dev
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## How It Works
|
|
71
|
+
|
|
72
|
+
The keeper bot now checks for the wallet in this order:
|
|
73
|
+
|
|
74
|
+
1. **Environment variable** (`KEEPER_PRIVATE_KEY`) - for Heroku
|
|
75
|
+
2. **Oracle wallet file** (`wallets/jackpot_oracle.json`) - for local development
|
|
76
|
+
3. **Main wallet file** (`~/.config/solana/id.json`) - fallback for local
|
|
77
|
+
|
|
78
|
+
This means:
|
|
79
|
+
- ✅ Works on Heroku (uses env var)
|
|
80
|
+
- ✅ Works locally (uses wallet file)
|
|
81
|
+
- ✅ Secure (private key not in git)
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Verification
|
|
86
|
+
|
|
87
|
+
After deployment, check the logs:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
heroku logs --tail --ps jackpot-keeper -a dubs-server-dev
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
You should see:
|
|
94
|
+
```
|
|
95
|
+
📂 Using wallet from KEEPER_PRIVATE_KEY environment variable
|
|
96
|
+
🤖 Complete Jackpot Keeper Bot
|
|
97
|
+
Wallet: FWUJCthDfPcgmTvdQWM5uofxxiYjqJFMMwiLYvS7LBFa
|
|
98
|
+
|
|
99
|
+
🚀 Keeper bot started!
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Troubleshooting
|
|
105
|
+
|
|
106
|
+
### Error: "No wallet found"
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Make sure env var is set
|
|
110
|
+
heroku config:get KEEPER_PRIVATE_KEY -a dubs-server-dev
|
|
111
|
+
|
|
112
|
+
# If empty, run setup again
|
|
113
|
+
./setup-heroku-keeper.sh
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Error: "Invalid private key"
|
|
117
|
+
|
|
118
|
+
The JSON array must be exactly as it appears in the wallet file:
|
|
119
|
+
- Start with `[`
|
|
120
|
+
- End with `]`
|
|
121
|
+
- 64 numbers separated by commas
|
|
122
|
+
- No extra spaces or newlines
|
|
123
|
+
|
|
124
|
+
### Keeper crashes on startup
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Check the logs for the exact error
|
|
128
|
+
heroku logs --tail --ps jackpot-keeper -a dubs-server-dev
|
|
129
|
+
|
|
130
|
+
# Restart it
|
|
131
|
+
heroku ps:restart jackpot-keeper -a dubs-server-dev
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Security Notes
|
|
137
|
+
|
|
138
|
+
⚠️ **Important Security Considerations:**
|
|
139
|
+
|
|
140
|
+
1. **Never commit wallet files to git** (they're already in `.gitignore`)
|
|
141
|
+
2. **Never share the private key** in public channels
|
|
142
|
+
3. **Use different wallets for different environments** (devnet vs mainnet)
|
|
143
|
+
4. **Rotate keys regularly** on mainnet
|
|
144
|
+
5. **Monitor wallet balance** - keeper needs SOL for transaction fees
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Wallet Info
|
|
149
|
+
|
|
150
|
+
The keeper uses the oracle wallet:
|
|
151
|
+
|
|
152
|
+
- **Address:** `FWUJCthDfPcgmTvdQWM5uofxxiYjqJFMMwiLYvS7LBFa`
|
|
153
|
+
- **File:** `wallets/jackpot_oracle.json` (local only)
|
|
154
|
+
- **Purpose:** Signs keeper transactions (open, lock, resolve rounds)
|
|
155
|
+
- **Network:** Devnet (test SOL only)
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## For Mainnet (Future)
|
|
160
|
+
|
|
161
|
+
When deploying to mainnet:
|
|
162
|
+
|
|
163
|
+
1. **Create a new mainnet wallet:**
|
|
164
|
+
```bash
|
|
165
|
+
solana-keygen new --outfile wallets/jackpot_oracle_mainnet.json
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
2. **Fund it with real SOL:**
|
|
169
|
+
```bash
|
|
170
|
+
solana transfer <NEW_WALLET_ADDRESS> 1.0 --url mainnet-beta
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
3. **Set on production Heroku:**
|
|
174
|
+
```bash
|
|
175
|
+
PRIVATE_KEY=$(cat wallets/jackpot_oracle_mainnet.json)
|
|
176
|
+
heroku config:set KEEPER_PRIVATE_KEY="$PRIVATE_KEY" -a dubs-server-prod
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
4. **Monitor balance regularly** - keeper pays gas fees
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Quick Reference
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# Setup keeper wallet
|
|
187
|
+
./setup-heroku-keeper.sh
|
|
188
|
+
|
|
189
|
+
# Deploy keeper
|
|
190
|
+
git push heroku-dev main
|
|
191
|
+
heroku ps:scale jackpot-keeper=1 -a dubs-server-dev
|
|
192
|
+
|
|
193
|
+
# Check logs
|
|
194
|
+
heroku logs --tail --ps jackpot-keeper -a dubs-server-dev
|
|
195
|
+
|
|
196
|
+
# Check wallet balance
|
|
197
|
+
solana balance FWUJCthDfPcgmTvdQWM5uofxxiYjqJFMMwiLYvS7LBFa --url devnet
|
|
198
|
+
|
|
199
|
+
# Restart keeper
|
|
200
|
+
heroku ps:restart jackpot-keeper -a dubs-server-dev
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
**Built with ❤️ on Solana** 🚀🎰
|
|
206
|
+
|