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,62 @@
1
+ -- ============================================
2
+ -- Migration: Add 'whats_new' notification type
3
+ -- ============================================
4
+ -- This migration updates the chat_notifications constraint
5
+ -- to allow 'whats_new' notification type for feature announcements
6
+
7
+ -- Drop all existing check constraints on notification_type
8
+ DO $$
9
+ DECLARE
10
+ r RECORD;
11
+ BEGIN
12
+ FOR r IN (
13
+ SELECT conname FROM pg_constraint
14
+ WHERE conrelid = 'chat_notifications'::regclass
15
+ AND contype = 'c'
16
+ AND conname LIKE '%notification_type%'
17
+ ) LOOP
18
+ EXECUTE 'ALTER TABLE chat_notifications DROP CONSTRAINT IF EXISTS ' || quote_ident(r.conname);
19
+ RAISE NOTICE 'Dropped constraint: %', r.conname;
20
+ END LOOP;
21
+ END $$;
22
+
23
+ -- Add the updated constraint with ALL notification types including whats_new
24
+ ALTER TABLE chat_notifications
25
+ ADD CONSTRAINT chat_notifications_notification_type_check
26
+ CHECK (notification_type IN (
27
+ 'reply',
28
+ 'mention',
29
+ 'friend_message',
30
+ 'reaction',
31
+ 'friend_request',
32
+ 'friend_request_accepted',
33
+ 'friend_request_declined',
34
+ 'referral',
35
+ 'game_joined',
36
+ 'game_invite',
37
+ 'game_starting_soon',
38
+ 'game_starting_now',
39
+ 'game_won',
40
+ 'game_lost',
41
+ 'payment_received',
42
+ 'payment_sent',
43
+ 'dm',
44
+ 'dm_message',
45
+ 'whats_new'
46
+ ));
47
+
48
+ -- Verify
49
+ DO $$
50
+ BEGIN
51
+ IF EXISTS (
52
+ SELECT 1 FROM pg_constraint
53
+ WHERE conname = 'chat_notifications_notification_type_check'
54
+ AND pg_get_constraintdef(oid) LIKE '%whats_new%'
55
+ ) THEN
56
+ RAISE NOTICE '✅ whats_new notification type added successfully';
57
+ ELSE
58
+ RAISE EXCEPTION '❌ Failed to add whats_new notification type';
59
+ END IF;
60
+ END $$;
61
+
62
+
@@ -0,0 +1,61 @@
1
+ -- ============================================
2
+ -- Migration: Add 'connect4_your_turn' notification type
3
+ -- ============================================
4
+ -- This migration updates the chat_notifications constraint
5
+ -- to allow 'connect4_your_turn' notification type for Connect4 games
6
+
7
+ -- Drop all existing check constraints on notification_type
8
+ DO $$
9
+ DECLARE
10
+ r RECORD;
11
+ BEGIN
12
+ FOR r IN (
13
+ SELECT conname FROM pg_constraint
14
+ WHERE conrelid = 'chat_notifications'::regclass
15
+ AND contype = 'c'
16
+ AND conname LIKE '%notification_type%'
17
+ ) LOOP
18
+ EXECUTE 'ALTER TABLE chat_notifications DROP CONSTRAINT IF EXISTS ' || quote_ident(r.conname);
19
+ RAISE NOTICE 'Dropped constraint: %', r.conname;
20
+ END LOOP;
21
+ END $$;
22
+
23
+ -- Add the updated constraint with ALL notification types including connect4_your_turn
24
+ ALTER TABLE chat_notifications
25
+ ADD CONSTRAINT chat_notifications_notification_type_check
26
+ CHECK (notification_type IN (
27
+ 'reply',
28
+ 'mention',
29
+ 'friend_message',
30
+ 'reaction',
31
+ 'friend_request',
32
+ 'friend_request_accepted',
33
+ 'friend_request_declined',
34
+ 'referral',
35
+ 'game_joined',
36
+ 'game_invite',
37
+ 'game_starting_soon',
38
+ 'game_starting_now',
39
+ 'game_won',
40
+ 'game_lost',
41
+ 'payment_received',
42
+ 'payment_sent',
43
+ 'dm',
44
+ 'dm_message',
45
+ 'whats_new',
46
+ 'connect4_your_turn'
47
+ ));
48
+
49
+ -- Verify
50
+ DO $$
51
+ BEGIN
52
+ IF EXISTS (
53
+ SELECT 1 FROM pg_constraint
54
+ WHERE conname = 'chat_notifications_notification_type_check'
55
+ AND pg_get_constraintdef(oid) LIKE '%connect4_your_turn%'
56
+ ) THEN
57
+ RAISE NOTICE '✅ connect4_your_turn notification type added successfully';
58
+ ELSE
59
+ RAISE EXCEPTION '❌ Failed to add connect4_your_turn notification type';
60
+ END IF;
61
+ END $$;
@@ -0,0 +1,55 @@
1
+ -- ============================================
2
+ -- Migration: Add Push Notification Tables
3
+ -- ============================================
4
+ -- This migration creates tables for Web Push notifications
5
+ -- to support PWA (seeker mode) push notifications
6
+
7
+ -- Create push_subscriptions table
8
+ CREATE TABLE IF NOT EXISTS push_subscriptions (
9
+ id SERIAL PRIMARY KEY,
10
+ user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
11
+ endpoint TEXT NOT NULL,
12
+ p256dh TEXT NOT NULL,
13
+ auth TEXT NOT NULL,
14
+ device_type VARCHAR(50) DEFAULT 'android_pwa',
15
+ created_at TIMESTAMP DEFAULT NOW(),
16
+ updated_at TIMESTAMP DEFAULT NOW(),
17
+ UNIQUE(user_id, endpoint)
18
+ );
19
+
20
+ -- Create index for fast user lookups
21
+ CREATE INDEX IF NOT EXISTS idx_push_subscriptions_user_id
22
+ ON push_subscriptions(user_id);
23
+
24
+ -- Create push_notification_preferences table (mirrors telegram_notification_preferences)
25
+ CREATE TABLE IF NOT EXISTS push_notification_preferences (
26
+ user_id INTEGER PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
27
+ notify_reply BOOLEAN DEFAULT true,
28
+ notify_reaction BOOLEAN DEFAULT true,
29
+ notify_friend_request BOOLEAN DEFAULT true,
30
+ notify_friend_request_accepted BOOLEAN DEFAULT true,
31
+ notify_friend_request_declined BOOLEAN DEFAULT true,
32
+ notify_referral BOOLEAN DEFAULT true,
33
+ notify_mention BOOLEAN DEFAULT true,
34
+ notify_friend_message BOOLEAN DEFAULT true,
35
+ notify_game_joined BOOLEAN DEFAULT true,
36
+ notify_game_invite BOOLEAN DEFAULT true,
37
+ created_at TIMESTAMP DEFAULT NOW(),
38
+ updated_at TIMESTAMP DEFAULT NOW()
39
+ );
40
+
41
+ -- Verify tables created
42
+ DO $$
43
+ BEGIN
44
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'push_subscriptions') THEN
45
+ RAISE NOTICE '✅ push_subscriptions table created successfully';
46
+ ELSE
47
+ RAISE EXCEPTION '❌ Failed to create push_subscriptions table';
48
+ END IF;
49
+
50
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'push_notification_preferences') THEN
51
+ RAISE NOTICE '✅ push_notification_preferences table created successfully';
52
+ ELSE
53
+ RAISE EXCEPTION '❌ Failed to create push_notification_preferences table';
54
+ END IF;
55
+ END $$;
@@ -0,0 +1,28 @@
1
+ -- ============================================
2
+ -- Migration: Add draw_team_players column
3
+ -- ============================================
4
+ -- This migration adds support for draw betting in EPL/soccer games
5
+ -- Run with: psql -d dubs_db -f scripts/migrations/006_add_draw_team_players.sql
6
+
7
+ -- Add draw_team_players column to games table
8
+ DO $$
9
+ BEGIN
10
+ IF NOT EXISTS (
11
+ SELECT 1 FROM information_schema.columns
12
+ WHERE table_name = 'games' AND column_name = 'draw_team_players'
13
+ ) THEN
14
+ ALTER TABLE games ADD COLUMN draw_team_players TEXT[] DEFAULT '{}';
15
+ RAISE NOTICE 'Added draw_team_players column to games table';
16
+ ELSE
17
+ RAISE NOTICE 'draw_team_players column already exists';
18
+ END IF;
19
+ END $$;
20
+
21
+ -- Verify the column was added
22
+ SELECT column_name, data_type, column_default
23
+ FROM information_schema.columns
24
+ WHERE table_name = 'games'
25
+ AND column_name IN ('home_team_players', 'away_team_players', 'draw_team_players')
26
+ ORDER BY column_name;
27
+
28
+ \echo '✅ Migration 006 complete: draw_team_players column added'
@@ -0,0 +1,62 @@
1
+ -- ============================================
2
+ -- Migration: Add 'game_cancelled' notification type
3
+ -- ============================================
4
+ -- This migration updates the chat_notifications constraint
5
+ -- to allow 'game_cancelled' notification type for cancelled games
6
+
7
+ -- Drop all existing check constraints on notification_type
8
+ DO $$
9
+ DECLARE
10
+ r RECORD;
11
+ BEGIN
12
+ FOR r IN (
13
+ SELECT conname FROM pg_constraint
14
+ WHERE conrelid = 'chat_notifications'::regclass
15
+ AND contype = 'c'
16
+ AND conname LIKE '%notification_type%'
17
+ ) LOOP
18
+ EXECUTE 'ALTER TABLE chat_notifications DROP CONSTRAINT IF EXISTS ' || quote_ident(r.conname);
19
+ RAISE NOTICE 'Dropped constraint: %', r.conname;
20
+ END LOOP;
21
+ END $$;
22
+
23
+ -- Add the updated constraint with ALL notification types including game_cancelled
24
+ ALTER TABLE chat_notifications
25
+ ADD CONSTRAINT chat_notifications_notification_type_check
26
+ CHECK (notification_type IN (
27
+ 'reply',
28
+ 'mention',
29
+ 'friend_message',
30
+ 'reaction',
31
+ 'friend_request',
32
+ 'friend_request_accepted',
33
+ 'friend_request_declined',
34
+ 'referral',
35
+ 'game_joined',
36
+ 'game_invite',
37
+ 'game_starting_soon',
38
+ 'game_starting_now',
39
+ 'game_won',
40
+ 'game_lost',
41
+ 'game_cancelled',
42
+ 'payment_received',
43
+ 'payment_sent',
44
+ 'dm',
45
+ 'dm_message',
46
+ 'whats_new',
47
+ 'connect4_your_turn'
48
+ ));
49
+
50
+ -- Verify
51
+ DO $$
52
+ BEGIN
53
+ IF EXISTS (
54
+ SELECT 1 FROM pg_constraint
55
+ WHERE conname = 'chat_notifications_notification_type_check'
56
+ AND pg_get_constraintdef(oid) LIKE '%game_cancelled%'
57
+ ) THEN
58
+ RAISE NOTICE '✅ game_cancelled notification type added successfully';
59
+ ELSE
60
+ RAISE EXCEPTION '❌ Failed to add game_cancelled notification type';
61
+ END IF;
62
+ END $$;
@@ -0,0 +1,8 @@
1
+ -- Migration: Add gif_url column to chat_messages table for GIF support
2
+ -- Date: 2026-01-20
3
+
4
+ -- Add gif_url column to chat_messages table
5
+ ALTER TABLE chat_messages ADD COLUMN IF NOT EXISTS gif_url TEXT;
6
+
7
+ -- Create index for efficient querying of messages with GIFs
8
+ CREATE INDEX IF NOT EXISTS idx_chat_messages_gif_url ON chat_messages(gif_url) WHERE gif_url IS NOT NULL;
@@ -0,0 +1,139 @@
1
+ -- ============================================
2
+ -- Migration 008: Add Connect4 columns to games table
3
+ -- ============================================
4
+ -- This migration adds columns required for Connect4 games:
5
+ -- - game_status: Game lifecycle status (waiting, playing, completed, cancelled)
6
+ -- - connect4_board: 6x7 game board state
7
+ -- - connect4_current_turn: Current player's turn (home/away)
8
+ -- - connect4_winner: Winner of the game (home/away/draw)
9
+ -- - connect4_winning_cells: Array of winning cell coordinates
10
+ -- - claim_signature: On-chain claim transaction signature
11
+ -- - completed_at: Timestamp when game ended
12
+ -- - invited_player: Wallet address for private game invites
13
+ --
14
+ -- Run with: psql -d dubs_db -f scripts/migrations/008_add_connect4_columns.sql
15
+
16
+ \echo 'Adding Connect4 columns to games table...'
17
+
18
+ -- Add game_status column
19
+ DO $$
20
+ BEGIN
21
+ IF NOT EXISTS (
22
+ SELECT 1 FROM information_schema.columns
23
+ WHERE table_name = 'games' AND column_name = 'game_status'
24
+ ) THEN
25
+ ALTER TABLE games ADD COLUMN game_status VARCHAR(50);
26
+ RAISE NOTICE 'Added game_status column';
27
+ ELSE
28
+ RAISE NOTICE 'game_status column already exists';
29
+ END IF;
30
+ END $$;
31
+
32
+ -- Add connect4_board column (JSONB for 6x7 2D array)
33
+ DO $$
34
+ BEGIN
35
+ IF NOT EXISTS (
36
+ SELECT 1 FROM information_schema.columns
37
+ WHERE table_name = 'games' AND column_name = 'connect4_board'
38
+ ) THEN
39
+ ALTER TABLE games ADD COLUMN connect4_board JSONB;
40
+ RAISE NOTICE 'Added connect4_board column';
41
+ ELSE
42
+ RAISE NOTICE 'connect4_board column already exists';
43
+ END IF;
44
+ END $$;
45
+
46
+ -- Add connect4_current_turn column
47
+ DO $$
48
+ BEGIN
49
+ IF NOT EXISTS (
50
+ SELECT 1 FROM information_schema.columns
51
+ WHERE table_name = 'games' AND column_name = 'connect4_current_turn'
52
+ ) THEN
53
+ ALTER TABLE games ADD COLUMN connect4_current_turn VARCHAR(10);
54
+ RAISE NOTICE 'Added connect4_current_turn column';
55
+ ELSE
56
+ RAISE NOTICE 'connect4_current_turn column already exists';
57
+ END IF;
58
+ END $$;
59
+
60
+ -- Add connect4_winner column
61
+ DO $$
62
+ BEGIN
63
+ IF NOT EXISTS (
64
+ SELECT 1 FROM information_schema.columns
65
+ WHERE table_name = 'games' AND column_name = 'connect4_winner'
66
+ ) THEN
67
+ ALTER TABLE games ADD COLUMN connect4_winner VARCHAR(10);
68
+ RAISE NOTICE 'Added connect4_winner column';
69
+ ELSE
70
+ RAISE NOTICE 'connect4_winner column already exists';
71
+ END IF;
72
+ END $$;
73
+
74
+ -- Add connect4_winning_cells column (JSONB for array of {row, col} objects)
75
+ DO $$
76
+ BEGIN
77
+ IF NOT EXISTS (
78
+ SELECT 1 FROM information_schema.columns
79
+ WHERE table_name = 'games' AND column_name = 'connect4_winning_cells'
80
+ ) THEN
81
+ ALTER TABLE games ADD COLUMN connect4_winning_cells JSONB;
82
+ RAISE NOTICE 'Added connect4_winning_cells column';
83
+ ELSE
84
+ RAISE NOTICE 'connect4_winning_cells column already exists';
85
+ END IF;
86
+ END $$;
87
+
88
+ -- Add claim_signature column
89
+ DO $$
90
+ BEGIN
91
+ IF NOT EXISTS (
92
+ SELECT 1 FROM information_schema.columns
93
+ WHERE table_name = 'games' AND column_name = 'claim_signature'
94
+ ) THEN
95
+ ALTER TABLE games ADD COLUMN claim_signature TEXT;
96
+ RAISE NOTICE 'Added claim_signature column';
97
+ ELSE
98
+ RAISE NOTICE 'claim_signature column already exists';
99
+ END IF;
100
+ END $$;
101
+
102
+ -- Add completed_at column
103
+ DO $$
104
+ BEGIN
105
+ IF NOT EXISTS (
106
+ SELECT 1 FROM information_schema.columns
107
+ WHERE table_name = 'games' AND column_name = 'completed_at'
108
+ ) THEN
109
+ ALTER TABLE games ADD COLUMN completed_at TIMESTAMP;
110
+ RAISE NOTICE 'Added completed_at column';
111
+ ELSE
112
+ RAISE NOTICE 'completed_at column already exists';
113
+ END IF;
114
+ END $$;
115
+
116
+ -- Add invited_player column (for private game invites)
117
+ DO $$
118
+ BEGIN
119
+ IF NOT EXISTS (
120
+ SELECT 1 FROM information_schema.columns
121
+ WHERE table_name = 'games' AND column_name = 'invited_player'
122
+ ) THEN
123
+ ALTER TABLE games ADD COLUMN invited_player VARCHAR(255);
124
+ RAISE NOTICE 'Added invited_player column';
125
+ ELSE
126
+ RAISE NOTICE 'invited_player column already exists';
127
+ END IF;
128
+ END $$;
129
+
130
+ -- Add index for game_status for faster filtering
131
+ CREATE INDEX IF NOT EXISTS idx_games_game_status ON games(game_status);
132
+
133
+ -- Add index for Connect4 game type queries
134
+ CREATE INDEX IF NOT EXISTS idx_games_type_status ON games(game_type, game_status);
135
+
136
+ -- Add index for private game lookups
137
+ CREATE INDEX IF NOT EXISTS idx_games_invited_player ON games(invited_player) WHERE invited_player IS NOT NULL;
138
+
139
+ \echo '✅ Connect4 columns migration complete!'
@@ -0,0 +1,22 @@
1
+ -- Migration 008: Add pool tracking for pari-mutuel betting
2
+ -- This tracks actual bet amounts per player instead of assuming fixed buy-in
3
+
4
+ -- Add pool amount columns to games table
5
+ ALTER TABLE games ADD COLUMN IF NOT EXISTS home_pool DECIMAL(20, 9) DEFAULT 0;
6
+ ALTER TABLE games ADD COLUMN IF NOT EXISTS away_pool DECIMAL(20, 9) DEFAULT 0;
7
+ ALTER TABLE games ADD COLUMN IF NOT EXISTS draw_pool DECIMAL(20, 9) DEFAULT 0;
8
+ ALTER TABLE games ADD COLUMN IF NOT EXISTS total_pool DECIMAL(20, 9) DEFAULT 0;
9
+
10
+ -- Add player_amounts as JSONB to store {walletAddress: amount} mapping
11
+ -- This parallels the on-chain player_amounts Vec<u64>
12
+ ALTER TABLE games ADD COLUMN IF NOT EXISTS player_amounts JSONB DEFAULT '{}';
13
+
14
+ -- Add index for efficient queries
15
+ CREATE INDEX IF NOT EXISTS idx_games_total_pool ON games(total_pool);
16
+
17
+ -- Comment explaining the columns
18
+ COMMENT ON COLUMN games.home_pool IS 'Total SOL bet on home team (pari-mutuel)';
19
+ COMMENT ON COLUMN games.away_pool IS 'Total SOL bet on away team (pari-mutuel)';
20
+ COMMENT ON COLUMN games.draw_pool IS 'Total SOL bet on draw (pari-mutuel, EPL only)';
21
+ COMMENT ON COLUMN games.total_pool IS 'Total SOL in the game pool';
22
+ COMMENT ON COLUMN games.player_amounts IS 'JSON mapping of walletAddress -> bet amount in SOL';
@@ -0,0 +1,174 @@
1
+ -- ============================================
2
+ -- Migration 009: Create Survivor Pool Tables
3
+ -- March Madness "Survive or Die" Pool Feature
4
+ -- ============================================
5
+ -- Run with: psql -d dubs_db -f scripts/migrations/009_create_survivor_pool_tables.sql
6
+
7
+ -- ============================================
8
+ -- 1. SURVIVOR POOLS (main pool configuration)
9
+ -- ============================================
10
+ CREATE TABLE IF NOT EXISTS survivor_pools (
11
+ id SERIAL PRIMARY KEY,
12
+ name VARCHAR(255) NOT NULL,
13
+ year INTEGER NOT NULL,
14
+ buy_in_lamports BIGINT NOT NULL,
15
+ current_round INTEGER DEFAULT 1,
16
+ round_deadline TIMESTAMP,
17
+ status VARCHAR(20) DEFAULT 'open' CHECK (status IN ('open', 'active', 'complete', 'cancelled')),
18
+ allow_same_team_twice BOOLEAN DEFAULT false,
19
+ solana_game_id VARCHAR(100),
20
+ created_by VARCHAR(44),
21
+ created_at TIMESTAMP DEFAULT NOW(),
22
+ updated_at TIMESTAMP DEFAULT NOW()
23
+ );
24
+
25
+ -- Index for querying active pools
26
+ CREATE INDEX IF NOT EXISTS idx_survivor_pools_status ON survivor_pools(status);
27
+ CREATE INDEX IF NOT EXISTS idx_survivor_pools_year ON survivor_pools(year);
28
+
29
+ COMMENT ON TABLE survivor_pools IS 'March Madness Survivor Pool configuration';
30
+ COMMENT ON COLUMN survivor_pools.buy_in_lamports IS 'Entry fee in lamports (1 SOL = 1,000,000,000 lamports)';
31
+ COMMENT ON COLUMN survivor_pools.current_round IS 'Current active round (1=First Four, 2=Round of 64, ... 7=Championship)';
32
+ COMMENT ON COLUMN survivor_pools.round_deadline IS 'Deadline to submit picks for current round';
33
+ COMMENT ON COLUMN survivor_pools.solana_game_id IS 'Links to on-chain escrow game account';
34
+
35
+ -- ============================================
36
+ -- 2. SURVIVOR ENTRIES (user participation)
37
+ -- ============================================
38
+ CREATE TABLE IF NOT EXISTS survivor_entries (
39
+ id SERIAL PRIMARY KEY,
40
+ pool_id INTEGER NOT NULL REFERENCES survivor_pools(id) ON DELETE CASCADE,
41
+ user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
42
+ wallet_address VARCHAR(44) NOT NULL,
43
+ is_alive BOOLEAN DEFAULT true,
44
+ eliminated_at_round INTEGER,
45
+ entry_tx_signature VARCHAR(100),
46
+ created_at TIMESTAMP DEFAULT NOW(),
47
+ updated_at TIMESTAMP DEFAULT NOW(),
48
+ UNIQUE(pool_id, user_id)
49
+ );
50
+
51
+ -- Indexes for querying entries
52
+ CREATE INDEX IF NOT EXISTS idx_survivor_entries_pool ON survivor_entries(pool_id);
53
+ CREATE INDEX IF NOT EXISTS idx_survivor_entries_user ON survivor_entries(user_id);
54
+ CREATE INDEX IF NOT EXISTS idx_survivor_entries_alive ON survivor_entries(pool_id, is_alive);
55
+ CREATE INDEX IF NOT EXISTS idx_survivor_entries_wallet ON survivor_entries(wallet_address);
56
+
57
+ COMMENT ON TABLE survivor_entries IS 'User entries in survivor pools';
58
+ COMMENT ON COLUMN survivor_entries.is_alive IS 'Whether user is still in the pool (not eliminated)';
59
+ COMMENT ON COLUMN survivor_entries.eliminated_at_round IS 'Round number when eliminated (null if still alive)';
60
+ COMMENT ON COLUMN survivor_entries.entry_tx_signature IS 'Solana transaction signature for entry payment';
61
+
62
+ -- ============================================
63
+ -- 3. SURVIVOR PICKS (user selections per round)
64
+ -- ============================================
65
+ CREATE TABLE IF NOT EXISTS survivor_picks (
66
+ id SERIAL PRIMARY KEY,
67
+ entry_id INTEGER NOT NULL REFERENCES survivor_entries(id) ON DELETE CASCADE,
68
+ round INTEGER NOT NULL,
69
+ team_id VARCHAR(50) NOT NULL,
70
+ team_name VARCHAR(100) NOT NULL,
71
+ team_seed INTEGER,
72
+ team_logo TEXT,
73
+ espn_game_id VARCHAR(50),
74
+ opponent_name VARCHAR(100),
75
+ opponent_seed INTEGER,
76
+ result VARCHAR(20) DEFAULT 'pending' CHECK (result IN ('pending', 'won', 'lost')),
77
+ created_at TIMESTAMP DEFAULT NOW(),
78
+ updated_at TIMESTAMP DEFAULT NOW(),
79
+ UNIQUE(entry_id, round)
80
+ );
81
+
82
+ -- Indexes for querying picks
83
+ CREATE INDEX IF NOT EXISTS idx_survivor_picks_entry ON survivor_picks(entry_id);
84
+ CREATE INDEX IF NOT EXISTS idx_survivor_picks_round ON survivor_picks(round);
85
+ CREATE INDEX IF NOT EXISTS idx_survivor_picks_team ON survivor_picks(team_id);
86
+ CREATE INDEX IF NOT EXISTS idx_survivor_picks_result ON survivor_picks(result);
87
+ CREATE INDEX IF NOT EXISTS idx_survivor_picks_espn ON survivor_picks(espn_game_id);
88
+
89
+ COMMENT ON TABLE survivor_picks IS 'User team selections for each round';
90
+ COMMENT ON COLUMN survivor_picks.team_id IS 'ESPN team ID';
91
+ COMMENT ON COLUMN survivor_picks.espn_game_id IS 'ESPN game ID for tracking results';
92
+ COMMENT ON COLUMN survivor_picks.result IS 'Pick outcome: pending, won, or lost';
93
+
94
+ -- ============================================
95
+ -- 4. SURVIVOR TOURNAMENT GAMES (bracket data)
96
+ -- ============================================
97
+ CREATE TABLE IF NOT EXISTS survivor_tournament_games (
98
+ id SERIAL PRIMARY KEY,
99
+ pool_id INTEGER NOT NULL REFERENCES survivor_pools(id) ON DELETE CASCADE,
100
+ round INTEGER NOT NULL,
101
+ espn_game_id VARCHAR(50) NOT NULL,
102
+ game_date TIMESTAMP,
103
+ team1_id VARCHAR(50) NOT NULL,
104
+ team1_name VARCHAR(100) NOT NULL,
105
+ team1_seed INTEGER,
106
+ team1_logo TEXT,
107
+ team2_id VARCHAR(50) NOT NULL,
108
+ team2_name VARCHAR(100) NOT NULL,
109
+ team2_seed INTEGER,
110
+ team2_logo TEXT,
111
+ winner_id VARCHAR(50),
112
+ team1_score INTEGER,
113
+ team2_score INTEGER,
114
+ status VARCHAR(20) DEFAULT 'scheduled' CHECK (status IN ('scheduled', 'live', 'final', 'postponed', 'cancelled')),
115
+ region VARCHAR(20),
116
+ created_at TIMESTAMP DEFAULT NOW(),
117
+ updated_at TIMESTAMP DEFAULT NOW(),
118
+ UNIQUE(pool_id, espn_game_id)
119
+ );
120
+
121
+ -- Indexes for querying tournament games
122
+ CREATE INDEX IF NOT EXISTS idx_survivor_games_pool ON survivor_tournament_games(pool_id);
123
+ CREATE INDEX IF NOT EXISTS idx_survivor_games_round ON survivor_tournament_games(round);
124
+ CREATE INDEX IF NOT EXISTS idx_survivor_games_status ON survivor_tournament_games(status);
125
+ CREATE INDEX IF NOT EXISTS idx_survivor_games_espn ON survivor_tournament_games(espn_game_id);
126
+ CREATE INDEX IF NOT EXISTS idx_survivor_games_teams ON survivor_tournament_games(team1_id, team2_id);
127
+
128
+ COMMENT ON TABLE survivor_tournament_games IS 'Tournament bracket games imported from ESPN';
129
+ COMMENT ON COLUMN survivor_tournament_games.round IS '1=First Four, 2=Round of 64, 3=Round of 32, 4=Sweet 16, 5=Elite 8, 6=Final Four, 7=Championship';
130
+ COMMENT ON COLUMN survivor_tournament_games.region IS 'EAST, WEST, SOUTH, MIDWEST for regional games';
131
+
132
+ -- ============================================
133
+ -- 5. SURVIVOR POOL PAYOUTS (winnings tracking)
134
+ -- ============================================
135
+ CREATE TABLE IF NOT EXISTS survivor_pool_payouts (
136
+ id SERIAL PRIMARY KEY,
137
+ pool_id INTEGER NOT NULL REFERENCES survivor_pools(id) ON DELETE CASCADE,
138
+ entry_id INTEGER NOT NULL REFERENCES survivor_entries(id) ON DELETE CASCADE,
139
+ amount_lamports BIGINT NOT NULL,
140
+ payout_tx_signature VARCHAR(100),
141
+ status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'processing', 'completed', 'failed')),
142
+ created_at TIMESTAMP DEFAULT NOW(),
143
+ updated_at TIMESTAMP DEFAULT NOW(),
144
+ UNIQUE(pool_id, entry_id)
145
+ );
146
+
147
+ -- Index for querying payouts
148
+ CREATE INDEX IF NOT EXISTS idx_survivor_payouts_pool ON survivor_pool_payouts(pool_id);
149
+ CREATE INDEX IF NOT EXISTS idx_survivor_payouts_status ON survivor_pool_payouts(status);
150
+
151
+ COMMENT ON TABLE survivor_pool_payouts IS 'Payout records for survivor pool winners';
152
+
153
+ -- ============================================
154
+ -- 6. ADD NOTIFICATION TYPE FOR SURVIVOR EVENTS
155
+ -- ============================================
156
+ -- This alters the existing notification type constraint if it exists
157
+ -- Safe to run multiple times
158
+
159
+ DO $$
160
+ BEGIN
161
+ -- Check if chat_notifications table exists and has a notification_type constraint
162
+ IF EXISTS (
163
+ SELECT 1 FROM information_schema.table_constraints
164
+ WHERE constraint_name = 'chat_notifications_notification_type_check'
165
+ AND table_name = 'chat_notifications'
166
+ ) THEN
167
+ ALTER TABLE chat_notifications DROP CONSTRAINT IF EXISTS chat_notifications_notification_type_check;
168
+ END IF;
169
+ END $$;
170
+
171
+ -- Note: The notification type enum/constraint update depends on the existing schema
172
+ -- Survivor-related notification types to add:
173
+ -- 'survivor_pool_joined', 'survivor_pick_reminder', 'survivor_round_result',
174
+ -- 'survivor_eliminated', 'survivor_payout'
@@ -0,0 +1,28 @@
1
+ -- ============================================
2
+ -- Migration 010: Add Survivor Pool Outcome Tracking
3
+ -- Tracks whether survivors win or house wins (all eliminated)
4
+ -- ============================================
5
+ -- Run with: psql -d dubs_db -f scripts/migrations/010_add_survivor_pool_outcome.sql
6
+
7
+ -- Add winner_type column to track outcome
8
+ ALTER TABLE survivor_pools
9
+ ADD COLUMN IF NOT EXISTS winner_type VARCHAR(20)
10
+ CHECK (winner_type IN ('survivors', 'house'));
11
+
12
+ -- Add completed_at timestamp
13
+ ALTER TABLE survivor_pools
14
+ ADD COLUMN IF NOT EXISTS completed_at TIMESTAMP;
15
+
16
+ -- Add comments
17
+ COMMENT ON COLUMN survivor_pools.winner_type IS 'Pool outcome: survivors (players split pot) or house (all eliminated, house keeps pot)';
18
+ COMMENT ON COLUMN survivor_pools.completed_at IS 'Timestamp when pool was completed/resolved';
19
+
20
+ -- Index for completed pools
21
+ CREATE INDEX IF NOT EXISTS idx_survivor_pools_winner_type ON survivor_pools(winner_type);
22
+ CREATE INDEX IF NOT EXISTS idx_survivor_pools_completed ON survivor_pools(completed_at);
23
+
24
+ -- Success message
25
+ DO $$
26
+ BEGIN
27
+ RAISE NOTICE 'Migration 010 complete: Added winner_type and completed_at columns to survivor_pools';
28
+ END $$;