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,516 @@
1
+ # Current Session: Draw Betting for EPL
2
+
3
+ ## Overview
4
+ Adding draw betting functionality for EPL/soccer games to the Dubs betting platform. Draw is a WINNING outcome (different from TIE which means refund). Only EPL/soccer games show the Draw option.
5
+
6
+ ## Status: DEPLOYED TO PRODUCTION ✅
7
+
8
+ All core functionality for draw betting is now deployed to mainnet:
9
+ - **Solana Contract**: Upgraded on mainnet (Jan 20, 2026)
10
+ - **Database**: Migration complete on dubs-server-prod
11
+ - **Backend**: Deployed to Heroku
12
+ - **Frontend**: Ready for deployment
13
+
14
+ ---
15
+
16
+ ## Production Deployment (Jan 20, 2026)
17
+
18
+ ### Contract Upgrade - MAINNET
19
+ **Program ID:** `85wJGp9uc8w2FeKX9CEHsudTo1UVCrmuRFy37oCcaoG1`
20
+ **Upgrade Signature:** `3NNB8oegaErNmbduWMaGZsUuUxvG9kVMMUpRZDmtKypowiHELjVtZAbeJbY9VzqC2qiAR3g4u1DAyqM14ZJ63EVX`
21
+ **Deployed Slot:** `394831708`
22
+
23
+ **Changes:**
24
+ - Added `Draw` variant to `TeamChoice` enum (byte value 2)
25
+ - Updated resolution logic to count draw bettors
26
+ - Competition check: `outcomes_with_bets < 2` triggers refund
27
+ - Backward compatible with existing Home/Away games
28
+
29
+ **Verification:**
30
+ - 4 existing unresolved games intact and unchanged
31
+ - Upgrade authority preserved: `57voP1Y8U4ztX2YAcHveK3JFvVRn1n6T6iUnHdAW6xr9`
32
+
33
+ ### Database Migration - PRODUCTION
34
+ **File:** `scripts/migrations/006_add_draw_team_players.sql`
35
+ **Result:** `draw_team_players TEXT[] DEFAULT '{}'` column added to games table
36
+
37
+ ### SOL Transfer
38
+ - **Returned:** 3.99 SOL to `GMFn5XxSDqDpC6kjZPXNmRqf2QM3Miibgwx1FGtTPQHU`
39
+ - **Transfer Signature:** `3GptVfrFzxHt8TU7PLBHzcqh694SAocTJ3WCcE6u988PfKZEWNR8xUgfRBagbhDLeE69ZmJXnjMSSDaUzdMctLmy`
40
+ - **Remaining in upgrade authority:** ~0.008 SOL (for future upgrades)
41
+
42
+ ---
43
+
44
+ ## Recent Bug Fixes (Jan 20, 2026) - Session 2
45
+
46
+ ### 29. Frontend - GameInviteCard Images Missing When Sharing from "You're In" Widget
47
+ **Files:**
48
+ - `app/v2/components/overlay/JoinGameOverlay.tsx`
49
+ - `app/v2/components/overlay/widgets/CreatorShareWidget.tsx`
50
+
51
+ **Problem:** When sharing a game to chat from the "You're In" widget in JoinGameOverlay, the GameInviteCard would show empty/missing images.
52
+
53
+ **Fixed:**
54
+ - Added `matchupImageUrl` to the share payload in `handleShareInChat()`
55
+ - Added `strThumb` for EPL thumbnail fallback
56
+ - Added `strTimestamp` and `sportsEventId` for complete data
57
+ - Same fields added to CreatorShareWidget's friend invite payload
58
+
59
+ ### 30. Backend - Team Name Mapping for Matchup Image Generation
60
+ **File:** `services/matchupImageService.js`
61
+
62
+ **Problem:** Bournemouth and other EPL teams showed fallback Premier League logo instead of team badge because TheSportsDB returns short names (e.g., "Bournemouth") but our files use full names (e.g., "afc_bournemouth.png").
63
+
64
+ **Fixed:**
65
+ - Added `TEAM_NAME_OVERRIDES` mapping for EPL teams:
66
+ - `'bournemouth'` → `'afc_bournemouth'`
67
+ - `'brighton'` / `'brighton & hove albion'` → `'brighton_and_hove_albion'`
68
+ - `'wolves'` → `'wolverhampton_wanderers'`
69
+ - `'spurs'` / `'tottenham'` → `'tottenham_hotspur'`
70
+ - `"nott'm forest"` / `'nottingham'` → `'nottingham_forest'`
71
+ - And others...
72
+ - Also added NHL (Utah Hockey Club) and NBA (LA Clippers) overrides
73
+
74
+ ### 31. Backend - S3 Image Cache Busting
75
+ **Files:**
76
+ - `services/s3Service.js`
77
+ - `routes/gamesRoutes.js`
78
+
79
+ **Problem:** Browser aggressively cached old S3 matchup images. Even after regenerating correct images, browsers showed stale cached versions.
80
+
81
+ **Fixed:**
82
+ - Added cache-busting timestamp to S3 URLs: `?v={timestamp}`
83
+ - Applied to both new uploads and reused existing images
84
+ - Example: `https://dubs-avatars-dev.s3.amazonaws.com/matchups/EPL/bournemouth_liverpool.jpg?v=1768941697099`
85
+
86
+ ### 32. Frontend - GameInviteCard Small Team Badges Using TheSportsDB URLs
87
+ **File:** `app/v2/components/chat/GameInviteCard.tsx`
88
+
89
+ **Problem:** The small team badges below the matchup image were using TheSportsDB URLs directly, not our custom mascot logos. Arsenal/Chelsea sometimes showed broken images.
90
+
91
+ **Fixed:**
92
+ - Imported `getTeamLogoProps` from `utils/teamLogos`
93
+ - Updated team badge `<img>` elements to use `getTeamLogoProps(teamName, league, fallbackUrl)`
94
+ - Now uses local logos first, falls back to TheSportsDB if local fails
95
+
96
+ ---
97
+
98
+ ## Recent Bug Fixes (Jan 20, 2026) - Session 1
99
+
100
+ ### 25. Frontend - useGameStatus Missing Draw Support
101
+ **File:** `app/v2/features/sports/components/my-games/useGameStatus.ts`
102
+
103
+ **Fixed:**
104
+ - Added `drawTeamPlayers` check when determining `myTeam`
105
+ - Added `drawTeamPlayers` to `userParticipated` check
106
+ - Draw bettors now correctly show as "Refundable" when `winner === null`
107
+
108
+ ### 26. Frontend - MyGamesWidget Missing Draw Checks
109
+ **File:** `app/v2/features/sports/components/my-games/MyGamesWidget.tsx`
110
+
111
+ **Fixed:**
112
+ - Added `drawTeamPlayers` check for `myTeam` determination
113
+ - Added `drawTeamPlayers` to `isRefundable` check
114
+ - Added `drawTeamPlayers` to `gameData` passed to overlays
115
+
116
+ ### 27. Frontend - Transaction History EPL Images
117
+ **Files:**
118
+ - `app/v2/features/transactions/types/transaction-types.ts`
119
+ - `app/v2/features/transactions/services/GameLinkingService.ts`
120
+ - `app/v2/features/transactions/components/TransactionHistoryOverlay.tsx`
121
+
122
+ **Fixed:**
123
+ - Added `matchupImageUrl` to `GameContext` interface
124
+ - Added `matchupImageUrl` to `GameData` interface
125
+ - Pass `matchupImageUrl` in sports gameContext (create/join/claim)
126
+ - Use `matchupImageUrl` as first choice for `preGeneratedUrl` in MatchupImage
127
+
128
+ ### 28. Frontend - Claim Transactions Not Linked (Cache Issue)
129
+ **File:** `app/v2/features/transactions/services/GameLinkingService.ts`
130
+
131
+ **Fixed:**
132
+ - Cache was serving stale data without `claimSignature` after claims
133
+ - Added detection for unlinked "receive" transactions
134
+ - Auto-refresh cache when unlinked receives found
135
+ - Re-link all transactions with fresh data containing claim signatures
136
+
137
+ ---
138
+
139
+ ## Earlier Bug Fixes (Jan 20, 2026)
140
+
141
+ ### 19. Frontend - MoneyLineTicker & MoneyLineDetail
142
+ **Files:**
143
+ - `app/v2/features/sports/components/live-scores/MoneyOnTheLineTicker.tsx`
144
+ - `app/v2/features/sports/components/live-scores/MoneyLineDetailModal.tsx`
145
+
146
+ **Fixed:**
147
+ - Added `drawTeamPlayers` to interfaces
148
+ - Updated total pot calculations to include draw bettors
149
+ - Updated player count displays to include draw bettors
150
+ - Fixed EPL image logic to use strThumb
151
+
152
+ ### 20. Backend - Missing draw_team_players in SQL Queries
153
+ **File:** `routes/gamesRoutes.js`
154
+
155
+ **Fixed:** Added `draw_team_players` to multiple SQL SELECT statements that were missing it:
156
+ - `/api/auth/games/user/:wallet` endpoint
157
+ - Various game lookup queries
158
+
159
+ ### 21. Frontend - Public Bets Not Showing
160
+ **Files:**
161
+ - `routes/gamesRoutes.js` (backend)
162
+ - `app/v2/features/sports/hooks/useFriendBetsForEvent.ts`
163
+ - `app/v2/features/sports/components/bet-flow/ExistingBetsScreen.tsx`
164
+
165
+ **Fixed:**
166
+ - Added new `publicBets` query to backend endpoint for non-friend bets
167
+ - Updated hook to process and include public bets
168
+ - Added new "Public Bets" section with Globe icon in ExistingBetsScreen
169
+
170
+ ### 22. Frontend - Locked Games Still Showing in QuickJoin
171
+ **Files:**
172
+ - `app/v2/features/sports/hooks/useFriendBetsForEvent.ts`
173
+ - `app/v2/features/sports/components/bet-flow/QuickJoinStep.tsx`
174
+
175
+ **Fixed:**
176
+ - Added `isGameLocked` check that verifies BOTH `isLocked` flag AND `lockTimestamp < now`
177
+ - Added warning UI for games that have already started
178
+ - Filter out locked games from existing bets list
179
+
180
+ **Key Learning:** The `is_locked` database flag isn't always updated when `lock_timestamp` passes. Must check both!
181
+
182
+ ### 23. Frontend - Draw Showing Wrong Team in ExistingBetsScreen
183
+ **File:** `app/v2/features/sports/components/bet-flow/ExistingBetsScreen.tsx`
184
+
185
+ **Fixed:**
186
+ - BetCard was showing "Backing Chelsea" when user picked draw
187
+ - Updated logic to explicitly check `teamChoice === 'draw'` and display "Draw" as team name
188
+ - Added handshake emoji (🤝) for draw bets in avatar display
189
+
190
+ ### 24. Frontend - MyGamesWidget Draw Support
191
+ **Files:**
192
+ - `app/v2/features/sports/components/my-games/myGames.types.ts`
193
+ - `app/v2/features/sports/components/my-games/useMyGames.ts`
194
+ - `app/v2/features/sports/components/my-games/MyGameRow.tsx`
195
+
196
+ **Fixed:**
197
+ - Added `drawTeamPlayers?: string[]` to Game interface
198
+ - Updated `teamChoice`, `myTeam`, `winner` types to include `'draw'`
199
+ - Updated `getTotalPlayers()` helper to include draw players
200
+ - Updated WebSocket handler for 'draw' team choice
201
+ - Updated avatar fetching to include draw players
202
+ - Updated `PlayerAvatarsStack` to include draw players in avatar display
203
+ - Updated `totalPot` calculation to include draw players
204
+ - Updated memo comparison to include drawTeamPlayers
205
+
206
+ ---
207
+
208
+ ## Completed Changes
209
+
210
+ ### 1. Database Migration
211
+ **File:** `scripts/migrations/006_add_draw_team_players.sql`
212
+ - Added `draw_team_players TEXT[] DEFAULT '{}'` column to games table
213
+
214
+ **File:** `scripts/setup-complete-database.sql`
215
+ - Updated schema to include `draw_team_players` column
216
+
217
+ ### 2. Backend - gamesRoutes.js
218
+ **File:** `routes/gamesRoutes.js`
219
+
220
+ - **Save game query** - Includes `draw_team_players` in INSERT/UPDATE
221
+ - **All read queries** - Return `drawTeamPlayers` in responses
222
+ - **totalPlayers calculations** - Include draw players: `(home + away + draw)`
223
+ - **participants arrays** - Include draw team players
224
+ - **Socket events** - `game:player_joined` includes `drawTeamCount`
225
+ - **Game state endpoint** - Returns `drawTeamCount`
226
+ - **League map for matchup images** - Added EPL/English Premier League mapping
227
+ - **EPL team ordering** - Uses Home vs Away (not Away @ Home) for matchup images
228
+ - **EPL image reuse disabled** - Always regenerates EPL images to avoid stale data
229
+ - **Public bets query** - Returns joinable bets from non-friends
230
+ - **Cache busting** - S3 URLs include `?v={timestamp}` parameter
231
+
232
+ ### 3. Backend - matchupImageService.js
233
+ **File:** `services/matchupImageService.js`
234
+
235
+ - **EPL team ordering** - Home team on left, Away team on right (lines 304-319)
236
+ - **League logo support** - Added EPL to supported leagues
237
+ - **Team name overrides** - Maps short names to file names (Bournemouth, Brighton, etc.)
238
+
239
+ ### 4. Backend - s3Service.js
240
+ **File:** `services/s3Service.js`
241
+
242
+ - **Force overwrite parameter** - `uploadMatchupImage()` accepts `forceOverwrite` param
243
+ - **EPL always overwrites** - Skips reuse check when `forceOverwrite=true`
244
+ - **Cache busting** - Appends `?v={timestamp}` to public URLs
245
+
246
+ ### 5. Backend - automaticGameOracle.js ✅
247
+ **File:** `services/automaticGameOracle.js`
248
+
249
+ - **Competition check updated** - Now considers draw players when determining if there's competition
250
+ - Old logic: Only checked if home OR away had 0 players → refund
251
+ - New logic: Checks if winner side has players AND loser side has players
252
+ - Example: If only draw bettors exist and game is tied → still refund (no losers)
253
+ - Example: If draw + away bettors exist and game is tied → draw bettors WIN
254
+ - **Notifications updated** - `sendGameResultNotifications()` now includes draw players
255
+ - **Web app notifications updated** - `sendWebAppNotifications()` now includes draw players
256
+ - **Referral commission updated** - `recordReferralCommission()` includes draw players in pot calculation
257
+ - **Winner encoding** - Already supported `winner = 'draw'` with byte encoding `[1, 2]`
258
+
259
+ ### 6. Frontend - PickWinnerWidget.tsx
260
+ **File:** `app/v2/components/overlay/widgets/PickWinnerWidget.tsx`
261
+
262
+ - Added `drawPlayerCount` and `drawOdds` props
263
+ - Updated `onJoin` type to include `'draw'`
264
+ - Added `isEPL` detection
265
+ - Added Draw button with 🤝 icon (EPL only)
266
+ - Updated selected team state type
267
+
268
+ ### 7. Frontend - JoinGameOverlay.tsx ✅
269
+ **File:** `app/v2/components/overlay/JoinGameOverlay.tsx`
270
+
271
+ - Added `drawTeamPlayers` to `GameData` interface
272
+ - Updated `totalPlayers` calculation to include draw
273
+ - Added `drawPlayerCount` and `drawOdds` calculations
274
+ - Updated `allPlayers` arrays to include draw
275
+ - Updated `hasUserJoined` checks for draw
276
+ - Updated socket event handler for draw team
277
+ - Fixed matchup image to use `matchupImageUrl` for all leagues
278
+ - **Refactored** to use `PlayersWidget` for player lists (reduced ~400 lines)
279
+ - **Refactored** to use `GameDetailsWidget` for game details (reduced ~130 lines)
280
+ - **Fixed competition detection** - Changed from `homePlayerCount === 0 || awayPlayerCount === 0` to counting sides with bettors
281
+ - Now correctly handles: Home+Draw, Away+Draw, etc. as valid competition
282
+ - **Updated `getDerivedWinner()`** - Now returns `'home' | 'away' | 'draw' | null`
283
+ - Checks `gameState?.winner` for 'draw'
284
+ - Checks `dbWinner` for 'draw'
285
+ - Derives draw winner when EPL + tied score + draw bettors exist
286
+ - **Fixed FinalScoreWidget call** - Now passes `derivedWinner` instead of `displayWinner`
287
+ - **Fixed `handleClaim()` function** - Now properly checks for `'draw'` winner when passing data to ClaimableGameOverlay
288
+ - **Fixed `handleShareInChat()`** - Now includes `matchupImageUrl`, `strThumb`, `strTimestamp`, `sportsEventId`
289
+
290
+ ### 8. Frontend - PlayersWidget.tsx (NEW)
291
+ **File:** `app/v2/components/overlay/widgets/PlayersWidget.tsx`
292
+
293
+ - New reusable widget for displaying player lists by team
294
+ - Shows Home, Away, and Draw team players with avatars
295
+ - Supports creator badge with crown icon
296
+ - Handles loading states and player profile navigation
297
+
298
+ ### 9. Frontend - GameDetailsWidget.tsx (NEW)
299
+ **File:** `app/v2/components/overlay/widgets/GameDetailsWidget.tsx`
300
+
301
+ - New reusable widget for displaying game details
302
+ - Shows title (formatted for EPL vs American sports conventions)
303
+ - Stats grid: Buy-in, Players count, Total Pot
304
+ - Game ID with copy button
305
+ - Game time with countdown display
306
+ - Currency conversion support
307
+
308
+ ### 10. Frontend - LiveScoreWidget.tsx ✅
309
+ **File:** `app/v2/components/overlay/widgets/LiveScoreWidget.tsx`
310
+
311
+ - Added `drawPlayerCount` prop
312
+ - Updated `gameState.winner` type to include `'draw'`
313
+ - EPL-aware tied score messaging:
314
+ - With draw bettors: "Draw bettors winning! (X bets)"
315
+ - Without draw bettors: "Score is tied - draw outcome looking likely!"
316
+ - Non-EPL: "Score is tied - anyone's game!"
317
+
318
+ ### 11. Frontend - FinalScoreWidget.tsx ✅
319
+ **File:** `app/v2/components/overlay/widgets/FinalScoreWidget.tsx`
320
+
321
+ - Added `'draw'` to winner type (`'home' | 'away' | 'draw' | 'tie' | null`)
322
+ - Added `userTeamChoice` support for `'draw'`
323
+ - Added `drawTeamPlayers` prop
324
+ - Added `isDrawWinner` check
325
+ - Updated `totalPlayers` to include draw players
326
+ - Updated `winningTeamCount` to include draw scenario
327
+ - Added "Draw bettors win!" message display
328
+ - Updated winner avatars to show draw bettors when draw wins
329
+
330
+ ### 12. Frontend - ClaimableGameOverlay.tsx ✅
331
+ **File:** `app/v2/components/overlay/ClaimableGameOverlay.tsx`
332
+
333
+ - Added `drawTeamPlayers` to gameData interface
334
+ - Added `'draw'` to winner type
335
+ - **Fixed competition detection** - Now counts sides with bettors (same as JoinGameOverlay)
336
+ - Added `isDrawWinner` check
337
+ - Updated `totalPlayers` to include draw players
338
+ - Updated `winningTeamCount` to handle draw winners
339
+ - Updated header text: "Draw Wins!" for draw victories
340
+ - Updated message: "You called the draw! 🤝"
341
+
342
+ ### 13. Frontend - GameInviteCard.tsx
343
+ **File:** `app/v2/components/chat/GameInviteCard.tsx`
344
+
345
+ - Player count includes `drawTeamCount`
346
+ - "Backing:" display shows "Draw" for draw bets
347
+ - EPL team ordering - Home vs Away display (not Away vs Home)
348
+ - `gameData` for claim overlay includes `drawTeamPlayers`
349
+ - **Uses local team logos** via `getTeamLogoProps()` with TheSportsDB fallback
350
+
351
+ ### 14. Frontend - ChatContext.tsx
352
+ **File:** `app/v2/contexts/ChatContext.tsx`
353
+
354
+ - `GameState` interface includes `drawTeamCount`
355
+ - `winner` type includes `'draw'`
356
+ - `userTeamChoice` type includes `'draw'`
357
+ - Socket handler updates `drawTeamCount`
358
+
359
+ ### 15. Frontend - chatSocket.ts
360
+ **File:** `app/v2/services/chatSocket.ts`
361
+
362
+ - `onPlayerJoined` callback includes `drawTeamCount` and `teamChoice: 'draw'`
363
+
364
+ ### 16. Frontend - sportsBetting.ts
365
+ **File:** `app/v2/services/sportsBetting.ts`
366
+
367
+ - Captures `matchupImageUrl` from save response
368
+ - Returns `matchupImageUrl` in result object
369
+
370
+ ### 17. Frontend - BetCreationModal.tsx
371
+ **File:** `app/v2/features/sports/components/BetCreationModal.tsx`
372
+
373
+ - Chat message shows "Draw" when user picks draw
374
+ - `gameInviteMetadata` includes `matchupImageUrl`
375
+
376
+ ### 18. Frontend - useSportsBettors.ts
377
+ **File:** `app/v2/features/sports/hooks/useSportsBettors.ts`
378
+
379
+ - `GameWithBettors` interface includes `drawTeamPlayers`
380
+ - Collects draw team players for avatar display on game cards
381
+
382
+ ---
383
+
384
+ ## Key Design Decisions
385
+
386
+ 1. **Draw vs Tie**: Draw is a WINNING outcome where draw bettors split the pot. Tie is when the game is cancelled/refunded (no competition).
387
+
388
+ 2. **EPL Only**: Draw betting only shown for EPL/English Premier League games.
389
+
390
+ 3. **Competition Logic**: Need at least 2 "sides" with bettors for valid competition:
391
+ - Home + Away = competition ✅
392
+ - Home + Draw = competition ✅
393
+ - Away + Draw = competition ✅
394
+ - All three = competition ✅
395
+ - Only one side = refund (no losers)
396
+
397
+ 4. **Team Display Order**:
398
+ - EPL: Home vs Away (soccer convention)
399
+ - Other leagues: Away @ Home (American sports convention)
400
+
401
+ 5. **Matchup Images**:
402
+ - EPL images always regenerated (no reuse) to avoid stale images
403
+ - Server generates image synchronously and returns URL in save response
404
+ - URL passed through to chat messages for display
405
+ - Cache-busting timestamp added to prevent browser caching issues
406
+
407
+ 6. **Lock Timestamp Check**: Must check BOTH `isLocked` flag AND `lockTimestamp < now` because the flag isn't always updated when timestamp passes.
408
+
409
+ 7. **Contract Backward Compatibility**: The `TeamChoice::Draw` variant (byte value 2) is purely additive - existing games with Home (0) and Away (1) deserialize correctly.
410
+
411
+ ---
412
+
413
+ ## Testing Checklist
414
+
415
+ ### Game Creation
416
+ - [x] EPL game shows Draw option in PickWinnerWidget
417
+ - [x] Non-EPL games do NOT show Draw option
418
+ - [x] Picking Draw shows correct chat message: "I just placed a X SOL bet on Draw"
419
+ - [x] Avatar appears on game card when betting on Draw
420
+ - [x] Matchup images show correct team logos (Bournemouth, Brighton, etc.)
421
+
422
+ ### Game Display
423
+ - [x] GameInviteCard shows "Backing: Draw" for draw bets
424
+ - [x] EPL games show "Home vs Away" (not "Away @ Home")
425
+ - [x] Players widget shows Draw section with bettors
426
+ - [x] Total player count includes draw bettors
427
+ - [x] ExistingBetsScreen shows "Backing Draw" (not wrong team name)
428
+ - [x] MyGamesWidget shows draw bettors in player count and avatars
429
+ - [x] Small team badges use local mascot logos (not TheSportsDB)
430
+ - [x] S3 images display fresh content (cache busting working)
431
+
432
+ ### Bet Flow
433
+ - [x] QuickJoinStep doesn't show locked/started games
434
+ - [x] Public bets from non-friends are visible and joinable
435
+ - [x] Locked game warning shown appropriately
436
+
437
+ ### Live Scores
438
+ - [ ] Tied EPL score with draw bettors shows "Draw bettors winning!"
439
+ - [ ] Tied EPL score without draw bettors shows "draw outcome looking likely"
440
+
441
+ ### Game Resolution (Draw Wins)
442
+ - [ ] Oracle resolves tied EPL game with draw bettors as `winner: 'draw'`
443
+ - [ ] JoinGameOverlay shows "Draw bettors win!" in FinalScoreWidget
444
+ - [ ] ClaimableGameOverlay shows "Draw Wins!" header
445
+ - [ ] ClaimableGameOverlay shows "You called the draw! 🤝"
446
+ - [ ] Prize calculation splits pot among draw bettors only
447
+
448
+ ### Claim Flow
449
+ - [ ] "Claim Prize" from JoinGameOverlay opens ClaimableGameOverlay with correct winner
450
+ - [ ] "Claim Prize" from GameInviteCard opens ClaimableGameOverlay with correct winner
451
+ - [ ] Draw winner can successfully claim on-chain
452
+
453
+ ---
454
+
455
+ ## Files Changed Summary
456
+
457
+ ### Backend (dubs-server)
458
+ - `routes/gamesRoutes.js` - Major changes for draw support + public bets + cache busting
459
+ - `services/automaticGameOracle.js` - Draw resolution logic
460
+ - `services/matchupImageService.js` - EPL team ordering + team name overrides
461
+ - `services/s3Service.js` - Force overwrite parameter + cache busting
462
+ - `scripts/migrations/006_add_draw_team_players.sql` - New migration
463
+
464
+ ### Frontend (dubs-jackpot-spa)
465
+ - `app/v2/components/overlay/widgets/PickWinnerWidget.tsx` - Draw button
466
+ - `app/v2/components/overlay/widgets/PlayersWidget.tsx` - NEW widget
467
+ - `app/v2/components/overlay/widgets/GameDetailsWidget.tsx` - NEW widget
468
+ - `app/v2/components/overlay/widgets/LiveScoreWidget.tsx` - Draw messaging
469
+ - `app/v2/components/overlay/widgets/FinalScoreWidget.tsx` - Draw winner display
470
+ - `app/v2/components/overlay/widgets/CreatorShareWidget.tsx` - matchupImageUrl in invites
471
+ - `app/v2/components/overlay/JoinGameOverlay.tsx` - Major refactor + draw support + share fix
472
+ - `app/v2/components/overlay/ClaimableGameOverlay.tsx` - Draw winner claim
473
+ - `app/v2/components/chat/GameInviteCard.tsx` - Draw display + local logos
474
+ - `app/v2/contexts/ChatContext.tsx` - Draw types
475
+ - `app/v2/services/chatSocket.ts` - Draw events
476
+ - `app/v2/services/sportsBetting.ts` - matchupImageUrl
477
+ - `app/v2/features/sports/components/BetCreationModal.tsx` - Draw message
478
+ - `app/v2/features/sports/hooks/useSportsBettors.ts` - Draw players
479
+ - `app/v2/features/sports/hooks/useFriendBetsForEvent.ts` - Public bets + lock check
480
+ - `app/v2/features/sports/components/bet-flow/ExistingBetsScreen.tsx` - Public bets + draw fix
481
+ - `app/v2/features/sports/components/bet-flow/QuickJoinStep.tsx` - Lock warning
482
+ - `app/v2/features/sports/components/live-scores/MoneyOnTheLineTicker.tsx` - Draw support
483
+ - `app/v2/features/sports/components/live-scores/MoneyLineDetailModal.tsx` - Draw support
484
+ - `app/v2/features/sports/components/my-games/myGames.types.ts` - Draw types
485
+ - `app/v2/features/sports/components/my-games/useMyGames.ts` - Draw support
486
+ - `app/v2/features/sports/components/my-games/useGameStatus.ts` - Draw status
487
+ - `app/v2/features/sports/components/my-games/MyGameRow.tsx` - Draw avatars/counts
488
+ - `app/v2/features/sports/components/my-games/MyGamesWidget.tsx` - Draw checks
489
+ - `app/v2/features/transactions/types/transaction-types.ts` - matchupImageUrl
490
+ - `app/v2/features/transactions/services/GameLinkingService.ts` - Cache refresh
491
+ - `app/v2/utils/teamLogos.ts` - Team name overrides (client-side)
492
+
493
+ ### Solana Contract (dubs)
494
+ - `programs/dubs_solana_program/src/lib.rs` - Added `Draw` to `TeamChoice` enum + updated resolution logic
495
+
496
+ ---
497
+
498
+ ## Deployment Status
499
+
500
+ | Environment | Contract | Database | Backend | Frontend |
501
+ |-------------|----------|----------|---------|----------|
502
+ | Devnet | ✅ Deployed | ✅ Migrated | ✅ Deployed | ✅ Deployed |
503
+ | **Mainnet** | ✅ Upgraded | ✅ Migrated | ✅ Deployed | 🔄 Pending |
504
+
505
+ ---
506
+
507
+ ## Pending / Future Work
508
+
509
+ 1. **Frontend deployment** - Merge and deploy to production
510
+
511
+ 2. **End-to-end testing on mainnet** - Wait for EPL games to resolve to test:
512
+ - Oracle resolution with draw winner
513
+ - Claim flow for draw winners
514
+ - Notification delivery for draw results
515
+
516
+ 3. **Monitor existing games** - 4 unresolved games should resolve correctly with new contract