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.
Files changed (304) hide show
  1. package/.claude/settings.local.json +280 -0
  2. package/CLAUDE.md +46 -0
  3. package/CONNECT4_PRODUCTION_DEPLOY.md +155 -0
  4. package/CURRENT_SESSION.md +171 -0
  5. package/CURRENT_SESSION_DRAW.md +516 -0
  6. package/MARCH_MADNESS_SURVIVOR.md +254 -0
  7. package/PANDA.md +166 -0
  8. package/Procfile +4 -0
  9. package/README.md +476 -0
  10. package/controllers/livescoresController.js +376 -0
  11. package/controllers/pickemController.js +554 -0
  12. package/controllers/survivorAdminController.js +887 -0
  13. package/controllers/survivorController.js +623 -0
  14. package/cron/oracleMonitor.js +77 -0
  15. package/cron/pickemOracleMonitor.js +73 -0
  16. package/data/jackpot-history.json +952 -0
  17. package/data/ncaaTeams.js +406 -0
  18. package/documentation/API_SECURITY_GUIDE.md +327 -0
  19. package/documentation/ARCADE_API.md +593 -0
  20. package/documentation/ARCADE_IMPLEMENTATION_SUMMARY.md +399 -0
  21. package/documentation/ARCADE_QUICKSTART.md +242 -0
  22. package/documentation/AUTOMATIC_MODE_ORACLE.md +321 -0
  23. package/documentation/BUG_FIX_COHORT_DATE_DISPLAY.md +171 -0
  24. package/documentation/CLAIM_MIGRATION_INSTRUCTIONS.md +52 -0
  25. package/documentation/CLAIM_STATUS_FIX.md +67 -0
  26. package/documentation/CLI_TOOL_GUIDE.md +372 -0
  27. package/documentation/COHORT_RETENTION_ANALYSIS.md +295 -0
  28. package/documentation/COHORT_RETENTION_IMPLEMENTATION_COMPLETE.md +461 -0
  29. package/documentation/COHORT_RETENTION_SUMMARY.md +204 -0
  30. package/documentation/COMPLETE_PROJECT_SUMMARY.md +490 -0
  31. package/documentation/DATABASE_QUERIES.md +269 -0
  32. package/documentation/DATABASE_RETENTION_POLICY.md +390 -0
  33. package/documentation/DATABASE_SETUP_GUIDE.md +361 -0
  34. package/documentation/DATABASE_SETUP_SUMMARY.md +247 -0
  35. package/documentation/DEMO_API_CURL_COMMANDS.md +656 -0
  36. package/documentation/DEPLOYMENT_SUMMARY.txt +100 -0
  37. package/documentation/DUPLICATE_NOTIFICATIONS_FIXED.md +201 -0
  38. package/documentation/EXCHANGE_RATES_INTEGRATION.md +371 -0
  39. package/documentation/FINAL_API_PROTECTION_TABLE.md +175 -0
  40. package/documentation/GAME_START_NOTIFICATIONS_DEPLOYMENT.md +256 -0
  41. package/documentation/GAME_START_NOTIFICATIONS_INTEGRATION.md +275 -0
  42. package/documentation/HEROKU_DEPLOYMENT.md +134 -0
  43. package/documentation/HEROKU_SCHEDULER_SETUP.md +271 -0
  44. package/documentation/JACKPOT_API.md +521 -0
  45. package/documentation/JACKPOT_DEPLOYMENT_GUIDE.md +362 -0
  46. package/documentation/JWT_IMPLEMENTATION_SUMMARY.md +373 -0
  47. package/documentation/JWT_QUICK_SETUP.md +268 -0
  48. package/documentation/JWT_TESTING_GUIDE.md +404 -0
  49. package/documentation/KEEPER_RECOVERY_GUIDE.md +381 -0
  50. package/documentation/KEEPER_SETUP.md +206 -0
  51. package/documentation/KEEPER_STATE_MACHINE.md +423 -0
  52. package/documentation/LATEST_PRODUCTION_SETUP.md +387 -0
  53. package/documentation/LOCAL_VOTING_TEST.md +279 -0
  54. package/documentation/ORACLE_FIXES_SUMMARY.md +188 -0
  55. package/documentation/ORACLE_POSTGRESQL_UPDATE.md +202 -0
  56. package/documentation/PAYMENT_DEPLOYMENT.md +209 -0
  57. package/documentation/PNL_TRACKING_SETUP.md +189 -0
  58. package/documentation/PREVENTING_LOCKUP_ERRORS.md +472 -0
  59. package/documentation/PRODUCTION_READY_SUMMARY.md +227 -0
  60. package/documentation/PUBLIC_VS_PRIVATE_ENDPOINTS.md +278 -0
  61. package/documentation/QUICK_AUTH_SETUP.md +99 -0
  62. package/documentation/QUICK_DEPLOY.md +224 -0
  63. package/documentation/QUICK_FIX.md +114 -0
  64. package/documentation/QUICK_START.md +152 -0
  65. package/documentation/REFEREE_MODE_GUIDE.md +392 -0
  66. package/documentation/RETENTION_CORE_ACTION_UPDATE.md +313 -0
  67. package/documentation/RETENTION_UPDATE_SUMMARY.md +108 -0
  68. package/documentation/RUN_MIGRATION_NOW.md +39 -0
  69. package/documentation/SCRIPTS_UPDATE_SUMMARY.md +251 -0
  70. package/documentation/SETUP_GUIDE.md +184 -0
  71. package/documentation/STATE_MACHINE_IMPLEMENTATION.md +250 -0
  72. package/documentation/TELEGRAM_NOTIFICATIONS_DIAGNOSIS.md +361 -0
  73. package/documentation/UNIFIED_ARCHITECTURE.md +231 -0
  74. package/documentation/VOTING_DEPLOYMENT_SUMMARY.md +392 -0
  75. package/documentation/WEBSOCKET_ARCHITECTURE.md +881 -0
  76. package/documentation/WHAT_WE_BUILT_TODAY.md +369 -0
  77. package/documentation/latest/LATEST_PRODUCTION_SETUP.md +865 -0
  78. package/ecosystem.config.js +65 -0
  79. package/env.template +125 -0
  80. package/middleware/apiKeyAuth.js +136 -0
  81. package/middleware/authenticate.js +214 -0
  82. package/middleware/developerUserAuth.js +76 -0
  83. package/middleware/socketAuth.js +69 -0
  84. package/package.json +49 -0
  85. package/postman/Dubs-API-v1-With-Voting.postman_collection.json +555 -0
  86. package/postman/Dubs-API-v1.postman_collection.json +205 -0
  87. package/postman/Dubs_Developer_API.postman_collection.json +662 -0
  88. package/postman/QUICKSTART.md +118 -0
  89. package/postman/QUICK_REFERENCE.md +246 -0
  90. package/postman/README.md +71 -0
  91. package/postman/VOTING_API_GUIDE.md +426 -0
  92. package/refactor/Animations.md +148 -0
  93. package/refactor/Chat.md +252 -0
  94. package/routes/actionsRoutes.js +699 -0
  95. package/routes/adminRoutes.js +370 -0
  96. package/routes/analyticsRoutes.js +1262 -0
  97. package/routes/arcadeRoutes.js +557 -0
  98. package/routes/authRoutes.js +2310 -0
  99. package/routes/avatarRoutes.js +85 -0
  100. package/routes/botRoutes.js +211 -0
  101. package/routes/chatRoutes.js +377 -0
  102. package/routes/cryptoPriceRoutes.js +105 -0
  103. package/routes/developerRoutes.js +4201 -0
  104. package/routes/deviceRoutes.js +214 -0
  105. package/routes/dmRoutes.js +167 -0
  106. package/routes/esportsRoutes.js +806 -0
  107. package/routes/exchangeRateRoutes.js +233 -0
  108. package/routes/gamesRoutes.js +3028 -0
  109. package/routes/jackpotRoutes.js +754 -0
  110. package/routes/keeperMonitoringRoutes.js +156 -0
  111. package/routes/keeperWebhookRoutes.js +466 -0
  112. package/routes/livescoresRoutes.js +31 -0
  113. package/routes/pickemAdminRoutes.js +199 -0
  114. package/routes/pickemRoutes.js +231 -0
  115. package/routes/playerStatsRoutes.js +147 -0
  116. package/routes/portfolioRoutes.js +217 -0
  117. package/routes/promoRoutes.js +418 -0
  118. package/routes/referralEarningsRoutes.js +392 -0
  119. package/routes/socialRoutes.js +459 -0
  120. package/routes/sportsRoutes.js +1271 -0
  121. package/routes/survivorAdminRoutes.js +345 -0
  122. package/routes/survivorRoutes.js +756 -0
  123. package/routes/uploadRoutes.js +256 -0
  124. package/routes/userProfileRoutes.js +244 -0
  125. package/routes/whatsNewRoutes.js +331 -0
  126. package/scripts/.claude/settings.local.json +15 -0
  127. package/scripts/README.md +170 -0
  128. package/scripts/RESTART_EVERYTHING.sh +104 -0
  129. package/scripts/add-claim-columns.sql +48 -0
  130. package/scripts/add-crypto-prices-cache.sql +27 -0
  131. package/scripts/add-exchange-rates-cache.sql +40 -0
  132. package/scripts/add-game-invite-column.sql +23 -0
  133. package/scripts/add-game-invite-notification.sql +33 -0
  134. package/scripts/add-game-invite-telegram-pref.sql +16 -0
  135. package/scripts/add-game-joined-notification.sql +16 -0
  136. package/scripts/add-game-joined-pref.js +40 -0
  137. package/scripts/add-game-joined-preference.sql +6 -0
  138. package/scripts/add-game-start-notifications.sql +41 -0
  139. package/scripts/add-notification-flags-to-games.sql +55 -0
  140. package/scripts/add-pending-game-dismissals.sql +19 -0
  141. package/scripts/add-preferred-currency.sql +34 -0
  142. package/scripts/add-winner-columns.js +61 -0
  143. package/scripts/add_mention_system.sql +53 -0
  144. package/scripts/add_payment_system.sql +96 -0
  145. package/scripts/add_sports_event_id_column.sql +22 -0
  146. package/scripts/analyze-cohort-data-heroku.js +276 -0
  147. package/scripts/analyze-cohort-data.js +295 -0
  148. package/scripts/analyze-prod-cohorts.sh +10 -0
  149. package/scripts/backfill-matchup-images.js +245 -0
  150. package/scripts/backfill-missing-signatures.js +175 -0
  151. package/scripts/backfill-referral-earnings.js +202 -0
  152. package/scripts/check-chat-schema.js +130 -0
  153. package/scripts/check-db.sh +14 -0
  154. package/scripts/check_oracle_in_game.js +54 -0
  155. package/scripts/cleanup-database.js +193 -0
  156. package/scripts/clear-notification-cache.js +85 -0
  157. package/scripts/convert-mnemonic.js +50 -0
  158. package/scripts/create-users-table.sql +44 -0
  159. package/scripts/debug-cohort-counts.js +248 -0
  160. package/scripts/debug-winner-calc.js +84 -0
  161. package/scripts/deploy-payment-system.sh +118 -0
  162. package/scripts/deploy-to-heroku.sh +63 -0
  163. package/scripts/diagnose-locked-round.js +143 -0
  164. package/scripts/dubs-cli.js +720 -0
  165. package/scripts/dump-account.js +65 -0
  166. package/scripts/find-vrf-offset.js +48 -0
  167. package/scripts/fix-chat-notifications-constraint.sql +122 -0
  168. package/scripts/fix-claim-columns.js +124 -0
  169. package/scripts/fix-constraint-now.js +44 -0
  170. package/scripts/fix-lock-timestamps.js +96 -0
  171. package/scripts/fix-locked-round.sh +126 -0
  172. package/scripts/fix-missing-badges.sql +91 -0
  173. package/scripts/fix-payment-notifications.sql +41 -0
  174. package/scripts/force-new-round.js +55 -0
  175. package/scripts/force-resolve-and-claim.js +278 -0
  176. package/scripts/important/README.md +115 -0
  177. package/scripts/important/authority-force-lock.js +197 -0
  178. package/scripts/important/authority-resolve-game.js +267 -0
  179. package/scripts/important/check-game-status.js +373 -0
  180. package/scripts/important/list-pending-games-by-version.js +270 -0
  181. package/scripts/important/reconcile-v1-v2-payouts.js +270 -0
  182. package/scripts/initialize-jackpot.js +111 -0
  183. package/scripts/jackpot/.claude/settings.local.json +10 -0
  184. package/scripts/jackpot/force-reset.js +84 -0
  185. package/scripts/jackpot/initialize-mainnet.js +100 -0
  186. package/scripts/jackpot/keeper.js +742 -0
  187. package/scripts/jackpot/status.js +107 -0
  188. package/scripts/jackpot/update-round-duration.js +143 -0
  189. package/scripts/keeper-bot.js +112 -0
  190. package/scripts/list-pending-games.js +131 -0
  191. package/scripts/migrate-chat-v2.js +127 -0
  192. package/scripts/migrate-chat-winners.js +84 -0
  193. package/scripts/migrate-chat.sh +17 -0
  194. package/scripts/migrate-game-invite.js +83 -0
  195. package/scripts/migrate-heroku-game-notifications.sh +159 -0
  196. package/scripts/migrations/001_analytics_tables.sql +422 -0
  197. package/scripts/migrations/002_add_matchup_image_url.sql +14 -0
  198. package/scripts/migrations/003_referral_earnings.sql +208 -0
  199. package/scripts/migrations/004_add_whats_new_notification_type.sql +62 -0
  200. package/scripts/migrations/005_add_connect4_your_turn_notification.sql +61 -0
  201. package/scripts/migrations/005_push_notifications.sql +55 -0
  202. package/scripts/migrations/006_add_draw_team_players.sql +28 -0
  203. package/scripts/migrations/006_add_game_cancelled_notification.sql +62 -0
  204. package/scripts/migrations/007_add_gif_url.sql +8 -0
  205. package/scripts/migrations/008_add_connect4_columns.sql +139 -0
  206. package/scripts/migrations/008_add_pool_tracking.sql +22 -0
  207. package/scripts/migrations/009_create_survivor_pool_tables.sql +174 -0
  208. package/scripts/migrations/010_add_survivor_pool_outcome.sql +28 -0
  209. package/scripts/migrations/011_create_developer_tables.sql +67 -0
  210. package/scripts/migrations/011_fix_keeper_tables.sql +85 -0
  211. package/scripts/migrations/012_create_developer_webhooks.sql +31 -0
  212. package/scripts/migrations/013_add_network_mode.sql +18 -0
  213. package/scripts/migrations/014_create_developer_app_users.sql +19 -0
  214. package/scripts/migrations/015_add_ui_config.sql +4 -0
  215. package/scripts/migrations/016_add_resolution_secret.sql +4 -0
  216. package/scripts/migrations/017_add_external_game_id.sql +3 -0
  217. package/scripts/migrations/018_create_pickem_tables.sql +115 -0
  218. package/scripts/migrations/019_expo_push_tokens.sql +19 -0
  219. package/scripts/migrations/create_whats_new_tables.sql +88 -0
  220. package/scripts/migrations/drop_live_games_tables.sql +34 -0
  221. package/scripts/open-jackpot-round.js +85 -0
  222. package/scripts/purge-all-data.sh +329 -0
  223. package/scripts/purge-all-data.sql +142 -0
  224. package/scripts/purge-heroku-data.sh +149 -0
  225. package/scripts/purge-heroku-data.sql +62 -0
  226. package/scripts/rebuild-heroku-database.sh +113 -0
  227. package/scripts/recover-funds.js +357 -0
  228. package/scripts/regenerate-epl-images.js +278 -0
  229. package/scripts/resize-s3-matchup-images.js +374 -0
  230. package/scripts/resolve-direct.js +88 -0
  231. package/scripts/resolve-mock-game.js +124 -0
  232. package/scripts/resolve-pickem-game.js +55 -0
  233. package/scripts/resolve-round-manual.js +83 -0
  234. package/scripts/resolve-stuck-game.js +382 -0
  235. package/scripts/resolve-stuck-round.js +42 -0
  236. package/scripts/run-connect4-migration.sh +16 -0
  237. package/scripts/run-mention-migration.sh +32 -0
  238. package/scripts/run-payment-migration.sh +51 -0
  239. package/scripts/run-preferred-currency-migration.sh +31 -0
  240. package/scripts/run-referral-earnings-migration.sh +32 -0
  241. package/scripts/run-survivor-outcome-migration.sh +16 -0
  242. package/scripts/seed-test-users.js +346 -0
  243. package/scripts/setup-auth-tables.js +78 -0
  244. package/scripts/setup-complete-database.sql +992 -0
  245. package/scripts/setup-database-fresh.sh +359 -0
  246. package/scripts/setup-heroku-keeper.sh +48 -0
  247. package/scripts/setup-keeper-database.js +83 -0
  248. package/scripts/setup-keeper-state-db.sql +110 -0
  249. package/scripts/setup-oracle.sh +39 -0
  250. package/scripts/setup-pnl-tracking.js +111 -0
  251. package/scripts/start-devnet.sh +14 -0
  252. package/scripts/test-arcade-devnet.sh +160 -0
  253. package/scripts/test-arcade-match.sh +109 -0
  254. package/scripts/test-automatic-mode.sh +239 -0
  255. package/scripts/test-connect4-cancel-claim.js +370 -0
  256. package/scripts/test-connect4-e2e.js +369 -0
  257. package/scripts/test-connect4-resolve.js +369 -0
  258. package/scripts/test-game-state-endpoint.js +136 -0
  259. package/scripts/test-invite-notification.js +86 -0
  260. package/scripts/test-jackpot-api.sh +71 -0
  261. package/scripts/test-poll-confirmation.js +267 -0
  262. package/scripts/test-resolve-game.js +271 -0
  263. package/scripts/test-resolve-signature.js +223 -0
  264. package/scripts/test-signature-preservation.js +124 -0
  265. package/scripts/test-state-machine.js +291 -0
  266. package/scripts/test-webhook-receiver.js +60 -0
  267. package/scripts/update-notification-constraint.js +52 -0
  268. package/scripts/verify-account-layout.js +145 -0
  269. package/scripts/verify-winner-algorithm.js +278 -0
  270. package/server.js +5259 -0
  271. package/services/arcadeMatchService.js +763 -0
  272. package/services/automaticGameOracle.js +1596 -0
  273. package/services/chatService.js +1612 -0
  274. package/services/connect4GameService.js +1049 -0
  275. package/services/connect4NotificationService.js +374 -0
  276. package/services/cryptoPriceService.js +223 -0
  277. package/services/customGameResolver.js +260 -0
  278. package/services/db.js +79 -0
  279. package/services/directMessageService.js +389 -0
  280. package/services/discordNotifications.js +160 -0
  281. package/services/exchangeRateService.js +289 -0
  282. package/services/expoPushService.js +314 -0
  283. package/services/gamesCacheService.js +539 -0
  284. package/services/jackpotHistory.js +331 -0
  285. package/services/jackpotService.js +856 -0
  286. package/services/keeperStateService.js +355 -0
  287. package/services/matchupImageService.js +591 -0
  288. package/services/notificationCacheService.js +407 -0
  289. package/services/pickemOracle.js +440 -0
  290. package/services/playerStatsService.js +389 -0
  291. package/services/portfolioService.js +555 -0
  292. package/services/promoService.js +757 -0
  293. package/services/promoTreasuryService.js +239 -0
  294. package/services/pushNotifications.js +353 -0
  295. package/services/redisService.js +422 -0
  296. package/services/referralEarningsService.js +728 -0
  297. package/services/s3Service.js +396 -0
  298. package/services/socialService.js +1202 -0
  299. package/services/survivorOracle.js +469 -0
  300. package/services/survivorSimulator.js +475 -0
  301. package/services/telegramNotifications.js +461 -0
  302. package/services/userProfileStatsService.js +1185 -0
  303. package/services/whatsNewService.js +388 -0
  304. 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
+