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,40 @@
1
+ -- Migration: Add exchange_rates_cache table
2
+ -- Purpose: Store cached exchange rates from external API to reduce API calls
3
+ -- Date: 2025-12-06
4
+
5
+ -- Create exchange rates cache table
6
+ CREATE TABLE IF NOT EXISTS exchange_rates_cache (
7
+ id SERIAL PRIMARY KEY,
8
+ base_currency VARCHAR(3) NOT NULL UNIQUE,
9
+ rates JSONB NOT NULL,
10
+ last_updated TIMESTAMP NOT NULL DEFAULT NOW(),
11
+ expires_at TIMESTAMP NOT NULL,
12
+ created_at TIMESTAMP DEFAULT NOW()
13
+ );
14
+
15
+ -- Create indexes for performance
16
+ CREATE INDEX IF NOT EXISTS idx_exchange_rates_base ON exchange_rates_cache(base_currency);
17
+ CREATE INDEX IF NOT EXISTS idx_exchange_rates_expires ON exchange_rates_cache(expires_at);
18
+
19
+ -- Add comments for documentation
20
+ COMMENT ON TABLE exchange_rates_cache IS 'Caches exchange rates from external API (5-minute TTL)';
21
+ COMMENT ON COLUMN exchange_rates_cache.base_currency IS 'Base currency code (e.g., USD, EUR)';
22
+ COMMENT ON COLUMN exchange_rates_cache.rates IS 'JSON object containing exchange rates for all supported currencies';
23
+ COMMENT ON COLUMN exchange_rates_cache.last_updated IS 'Timestamp when rates were last fetched from API';
24
+ COMMENT ON COLUMN exchange_rates_cache.expires_at IS 'Timestamp when cache entry expires';
25
+
26
+ -- Sample query to view cached rates
27
+ -- SELECT base_currency, rates, last_updated, expires_at FROM exchange_rates_cache;
28
+
29
+ -- Sample query to clear expired entries
30
+ -- DELETE FROM exchange_rates_cache WHERE expires_at < NOW();
31
+
32
+ COMMIT;
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
@@ -0,0 +1,23 @@
1
+ -- Add game_invite_metadata column to chat_messages table
2
+ -- This allows rich game invite cards in chat
3
+
4
+ ALTER TABLE chat_messages
5
+ ADD COLUMN IF NOT EXISTS game_invite_metadata JSONB;
6
+
7
+ -- Create index for faster queries on game invites
8
+ CREATE INDEX IF NOT EXISTS idx_chat_messages_game_invite
9
+ ON chat_messages ((game_invite_metadata->>'gameId'))
10
+ WHERE game_invite_metadata IS NOT NULL;
11
+
12
+ SELECT 'Migration complete: game_invite_metadata column added' AS status;
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
@@ -0,0 +1,33 @@
1
+ -- Add game_invite to notification type constraint
2
+ -- Run this script to update your existing database
3
+
4
+ -- Drop the old constraint
5
+ ALTER TABLE chat_notifications
6
+ DROP CONSTRAINT IF EXISTS chat_notifications_notification_type_check;
7
+
8
+ -- Add the new constraint with game_invite included
9
+ ALTER TABLE chat_notifications
10
+ ADD CONSTRAINT chat_notifications_notification_type_check
11
+ CHECK (notification_type IN (
12
+ 'reply',
13
+ 'mention',
14
+ 'friend_message',
15
+ 'reaction',
16
+ 'friend_request',
17
+ 'friend_request_accepted',
18
+ 'friend_request_declined',
19
+ 'referral',
20
+ 'game_joined',
21
+ 'game_invite'
22
+ ));
23
+
24
+ SELECT 'Migration complete: game_invite notification type added' AS status;
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
@@ -0,0 +1,16 @@
1
+ -- Add notify_game_invite to Telegram notification preferences
2
+ -- Run this to update existing databases
3
+
4
+ ALTER TABLE telegram_notification_preferences
5
+ ADD COLUMN IF NOT EXISTS notify_game_invite BOOLEAN DEFAULT true;
6
+
7
+ SELECT 'Migration complete: notify_game_invite preference added' AS status;
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
@@ -0,0 +1,16 @@
1
+ -- Add game_joined notification type and notification_data column
2
+
3
+ -- Drop old constraint
4
+ ALTER TABLE chat_notifications
5
+ DROP CONSTRAINT IF EXISTS chat_notifications_notification_type_check;
6
+
7
+ -- Add new constraint with game_joined
8
+ ALTER TABLE chat_notifications
9
+ ADD CONSTRAINT chat_notifications_notification_type_check
10
+ CHECK (notification_type IN ('reply', 'mention', 'friend_message', 'reaction', 'friend_request', 'friend_request_accepted', 'friend_request_declined', 'referral', 'game_joined'));
11
+
12
+ -- Add notification_data column if it doesn't exist
13
+ ALTER TABLE chat_notifications
14
+ ADD COLUMN IF NOT EXISTS notification_data JSONB;
15
+
16
+ SELECT 'Migration complete: game_joined notification type added' AS status;
@@ -0,0 +1,40 @@
1
+ // Add notify_game_joined preference
2
+ require('dotenv').config();
3
+ const { Pool } = require('pg');
4
+
5
+ const pool = new Pool({
6
+ connectionString: process.env.DATABASE_URL,
7
+ ssl: process.env.DATABASE_URL && (process.env.DATABASE_URL.includes('amazonaws') || process.env.DATABASE_URL.includes('heroku'))
8
+ ? { rejectUnauthorized: false }
9
+ : false
10
+ });
11
+
12
+ async function addPreference() {
13
+ try {
14
+ console.log('🔧 Adding notify_game_joined preference...');
15
+
16
+ await pool.query(`
17
+ ALTER TABLE telegram_notification_preferences
18
+ ADD COLUMN IF NOT EXISTS notify_game_joined BOOLEAN DEFAULT true;
19
+ `);
20
+
21
+ console.log('✅ Preference added successfully! All users will receive game join notifications by default.');
22
+ process.exit(0);
23
+ } catch (error) {
24
+ console.error('❌ Error:', error.message);
25
+ process.exit(1);
26
+ }
27
+ }
28
+
29
+ addPreference();
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
@@ -0,0 +1,6 @@
1
+ -- Add notify_game_joined to Telegram notification preferences
2
+
3
+ ALTER TABLE telegram_notification_preferences
4
+ ADD COLUMN IF NOT EXISTS notify_game_joined BOOLEAN DEFAULT true;
5
+
6
+ SELECT 'Migration complete: notify_game_joined preference added' AS status;
@@ -0,0 +1,41 @@
1
+ -- Migration: Add Game Start Notification Types
2
+ -- Run this on existing databases to add game_starting_soon and game_starting_now notification types
3
+
4
+ -- Drop existing constraint
5
+ ALTER TABLE chat_notifications
6
+ DROP CONSTRAINT IF EXISTS chat_notifications_notification_type_check;
7
+
8
+ -- Add new constraint with game start notification types
9
+ ALTER TABLE chat_notifications
10
+ ADD CONSTRAINT chat_notifications_notification_type_check
11
+ CHECK (notification_type IN (
12
+ 'reply',
13
+ 'mention',
14
+ 'friend_message',
15
+ 'reaction',
16
+ 'friend_request',
17
+ 'friend_request_accepted',
18
+ 'friend_request_declined',
19
+ 'referral',
20
+ 'game_joined',
21
+ 'game_invite',
22
+ 'game_starting_soon',
23
+ 'game_starting_now'
24
+ ));
25
+
26
+ -- Verify the constraint was updated
27
+ SELECT constraint_name, check_clause
28
+ FROM information_schema.check_constraints
29
+ WHERE constraint_name = 'chat_notifications_notification_type_check';
30
+
31
+ -- Done!
32
+ SELECT 'Migration completed successfully!' AS status;
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
@@ -0,0 +1,55 @@
1
+ -- Migration: Add notification flag columns to games table
2
+ -- Date: 2025-12-03
3
+ -- Purpose: Add columns to track when lock notifications have been sent
4
+
5
+ -- Add lock_notification_sent_10min column if it doesn't exist
6
+ DO $$
7
+ BEGIN
8
+ IF NOT EXISTS (
9
+ SELECT 1 FROM information_schema.columns
10
+ WHERE table_name = 'games'
11
+ AND column_name = 'lock_notification_sent_10min'
12
+ ) THEN
13
+ ALTER TABLE games
14
+ ADD COLUMN lock_notification_sent_10min BOOLEAN DEFAULT false;
15
+
16
+ RAISE NOTICE 'Added lock_notification_sent_10min column to games table';
17
+ ELSE
18
+ RAISE NOTICE 'Column lock_notification_sent_10min already exists';
19
+ END IF;
20
+ END $$;
21
+
22
+ -- Add lock_notification_sent_now column if it doesn't exist
23
+ DO $$
24
+ BEGIN
25
+ IF NOT EXISTS (
26
+ SELECT 1 FROM information_schema.columns
27
+ WHERE table_name = 'games'
28
+ AND column_name = 'lock_notification_sent_now'
29
+ ) THEN
30
+ ALTER TABLE games
31
+ ADD COLUMN lock_notification_sent_now BOOLEAN DEFAULT false;
32
+
33
+ RAISE NOTICE 'Added lock_notification_sent_now column to games table';
34
+ ELSE
35
+ RAISE NOTICE 'Column lock_notification_sent_now already exists';
36
+ END IF;
37
+ END $$;
38
+
39
+ -- Verify columns were added
40
+ SELECT
41
+ column_name,
42
+ data_type,
43
+ column_default
44
+ FROM information_schema.columns
45
+ WHERE table_name = 'games'
46
+ AND column_name IN ('lock_notification_sent_10min', 'lock_notification_sent_now')
47
+ ORDER BY column_name;
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+
@@ -0,0 +1,19 @@
1
+ -- Pending game dismissals (tracks which pending game deeplinks user has dismissed)
2
+ CREATE TABLE IF NOT EXISTS pending_game_dismissals (
3
+ id SERIAL PRIMARY KEY,
4
+ wallet_address VARCHAR(44) NOT NULL,
5
+ game_id VARCHAR(255) NOT NULL,
6
+ dismissed_at TIMESTAMP DEFAULT NOW(),
7
+ UNIQUE(wallet_address, game_id)
8
+ );
9
+
10
+ CREATE INDEX IF NOT EXISTS idx_pending_dismissals_wallet ON pending_game_dismissals(wallet_address);
11
+ CREATE INDEX IF NOT EXISTS idx_pending_dismissals_game ON pending_game_dismissals(game_id);
12
+
13
+ SELECT 'Migration complete: pending_game_dismissals table created' AS status;
14
+
15
+
16
+
17
+
18
+
19
+
@@ -0,0 +1,34 @@
1
+ -- Migration: Add preferred_currency to users table
2
+ -- Purpose: Allow users to save their preferred display currency
3
+ -- Date: 2025-12-06
4
+
5
+ -- Add preferred_currency column to users table
6
+ ALTER TABLE users
7
+ ADD COLUMN IF NOT EXISTS preferred_currency VARCHAR(3) DEFAULT 'USD';
8
+
9
+ -- Add check constraint to ensure only supported currencies
10
+ ALTER TABLE users
11
+ ADD CONSTRAINT check_preferred_currency
12
+ CHECK (preferred_currency IN ('USD', 'EUR', 'CAD', 'GBP', 'JPY', 'AUD', 'CHF', 'CNY', 'SEK', 'NZD'));
13
+
14
+ -- Create index for faster queries
15
+ CREATE INDEX IF NOT EXISTS idx_users_preferred_currency ON users(preferred_currency);
16
+
17
+ -- Add comment for documentation
18
+ COMMENT ON COLUMN users.preferred_currency IS 'User preferred display currency (3-letter code)';
19
+
20
+ -- Sample query to update a user's preferred currency
21
+ -- UPDATE users SET preferred_currency = 'EUR' WHERE wallet_address = 'user_wallet_address';
22
+
23
+ -- Sample query to view users by preferred currency
24
+ -- SELECT preferred_currency, COUNT(*) FROM users GROUP BY preferred_currency;
25
+
26
+ COMMIT;
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
@@ -0,0 +1,61 @@
1
+ /**
2
+ * 🔥 Add Winner Announcement Columns to Chat
3
+ *
4
+ * Run with: heroku run node scripts/add-winner-columns.js
5
+ */
6
+
7
+ const { Pool } = require('pg');
8
+
9
+ async function addColumns() {
10
+ const pool = new Pool({
11
+ connectionString: process.env.DATABASE_URL,
12
+ ssl: process.env.DATABASE_URL ? { rejectUnauthorized: false } : false,
13
+ });
14
+
15
+ try {
16
+ console.log('🚀 Adding winner announcement columns to chat_messages...\n');
17
+
18
+ // Add the columns
19
+ await pool.query(`
20
+ ALTER TABLE chat_messages
21
+ ADD COLUMN IF NOT EXISTS is_winner_announcement BOOLEAN DEFAULT FALSE,
22
+ ADD COLUMN IF NOT EXISTS win_amount NUMERIC(20, 9),
23
+ ADD COLUMN IF NOT EXISTS round_id INTEGER;
24
+ `);
25
+
26
+ console.log('✅ Columns added successfully!');
27
+
28
+ // Create index
29
+ await pool.query(`
30
+ CREATE INDEX IF NOT EXISTS idx_chat_winner ON chat_messages(is_winner_announcement);
31
+ `);
32
+
33
+ console.log('✅ Index created!');
34
+
35
+ // Verify
36
+ const result = await pool.query(`
37
+ SELECT column_name
38
+ FROM information_schema.columns
39
+ WHERE table_name = 'chat_messages'
40
+ ORDER BY ordinal_position;
41
+ `);
42
+
43
+ console.log('\n📊 Current columns:');
44
+ result.rows.forEach(row => {
45
+ const isNew = ['is_winner_announcement', 'win_amount', 'round_id'].includes(row.column_name);
46
+ console.log(` ${row.column_name}${isNew ? ' 🔥 NEW!' : ''}`);
47
+ });
48
+
49
+ console.log('\n🎉 Migration complete! Winner announcements are ready!');
50
+
51
+ await pool.end();
52
+ } catch (error) {
53
+ console.error('❌ Migration failed:', error.message);
54
+ console.error(error);
55
+ await pool.end();
56
+ process.exit(1);
57
+ }
58
+ }
59
+
60
+ addColumns();
61
+
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Database Migration: Add @Mention System
3
+ *
4
+ * Creates message_mentions table to track user mentions in chat messages
5
+ */
6
+
7
+ -- Create message_mentions table
8
+ CREATE TABLE IF NOT EXISTS message_mentions (
9
+ id SERIAL PRIMARY KEY,
10
+ message_id INTEGER NOT NULL REFERENCES chat_messages(id) ON DELETE CASCADE,
11
+ mentioned_user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
12
+ created_at TIMESTAMP DEFAULT NOW(),
13
+ UNIQUE(message_id, mentioned_user_id)
14
+ );
15
+
16
+ -- Create indexes for performance
17
+ CREATE INDEX IF NOT EXISTS idx_message_mentions_user ON message_mentions(mentioned_user_id);
18
+ CREATE INDEX IF NOT EXISTS idx_message_mentions_message ON message_mentions(message_id);
19
+
20
+ -- Update chat_notifications constraint to include 'mention' type (if not already present)
21
+ -- This is idempotent - safe to run multiple times
22
+ ALTER TABLE chat_notifications
23
+ DROP CONSTRAINT IF EXISTS chat_notifications_notification_type_check;
24
+
25
+ ALTER TABLE chat_notifications
26
+ ADD CONSTRAINT chat_notifications_notification_type_check
27
+ CHECK (notification_type IN (
28
+ 'reply',
29
+ 'mention',
30
+ 'friend_message',
31
+ 'reaction',
32
+ 'friend_request',
33
+ 'friend_request_accepted',
34
+ 'friend_request_declined',
35
+ 'referral',
36
+ 'game_joined',
37
+ 'game_invite'
38
+ ));
39
+
40
+ -- Success message
41
+ DO $$
42
+ BEGIN
43
+ RAISE NOTICE '✅ Mention system tables created successfully!';
44
+ END $$;
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
@@ -0,0 +1,96 @@
1
+ -- ========================================
2
+ -- Payment Mention System Migration
3
+ -- ========================================
4
+ -- Adds support for SOL payments through chat mentions
5
+ -- Usage: "@username $amount" sends SOL to mentioned user
6
+
7
+ -- Create chat_payments table
8
+ CREATE TABLE IF NOT EXISTS chat_payments (
9
+ id SERIAL PRIMARY KEY,
10
+
11
+ -- Message reference
12
+ message_id INTEGER NOT NULL REFERENCES chat_messages(id) ON DELETE CASCADE,
13
+
14
+ -- Sender
15
+ sender_user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
16
+ sender_wallet VARCHAR(100) NOT NULL,
17
+
18
+ -- Recipient
19
+ recipient_user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
20
+ recipient_wallet VARCHAR(100) NOT NULL,
21
+
22
+ -- Payment details
23
+ amount_sol NUMERIC(20, 9) NOT NULL, -- Amount in SOL
24
+ transaction_signature VARCHAR(200) UNIQUE NOT NULL, -- Solana tx signature
25
+
26
+ -- Status tracking
27
+ status VARCHAR(20) NOT NULL DEFAULT 'pending'
28
+ CHECK (status IN ('pending', 'confirmed', 'failed')),
29
+ error_message TEXT,
30
+
31
+ -- Timestamps
32
+ created_at TIMESTAMP DEFAULT NOW(),
33
+ confirmed_at TIMESTAMP,
34
+
35
+ -- Prevent duplicate payments for same message
36
+ UNIQUE(message_id, sender_user_id, recipient_user_id)
37
+ );
38
+
39
+ -- Indexes for performance
40
+ CREATE INDEX IF NOT EXISTS idx_payments_sender ON chat_payments(sender_user_id);
41
+ CREATE INDEX IF NOT EXISTS idx_payments_recipient ON chat_payments(recipient_user_id);
42
+ CREATE INDEX IF NOT EXISTS idx_payments_message ON chat_payments(message_id);
43
+ CREATE INDEX IF NOT EXISTS idx_payments_signature ON chat_payments(transaction_signature);
44
+ CREATE INDEX IF NOT EXISTS idx_payments_status ON chat_payments(status);
45
+ CREATE INDEX IF NOT EXISTS idx_payments_created_at ON chat_payments(created_at DESC);
46
+
47
+ -- Update chat_notifications constraint to include payment types
48
+ ALTER TABLE chat_notifications
49
+ DROP CONSTRAINT IF EXISTS chat_notifications_notification_type_check;
50
+
51
+ ALTER TABLE chat_notifications
52
+ ADD CONSTRAINT chat_notifications_notification_type_check
53
+ CHECK (notification_type IN (
54
+ 'reply',
55
+ 'mention',
56
+ 'friend_message',
57
+ 'reaction',
58
+ 'friend_request',
59
+ 'friend_request_accepted',
60
+ 'friend_request_declined',
61
+ 'referral',
62
+ 'game_joined',
63
+ 'game_invite',
64
+ 'game_starting_soon',
65
+ 'game_starting_now',
66
+ 'payment_received', -- NEW: User receives SOL payment
67
+ 'payment_sent' -- NEW: User's payment was confirmed
68
+ ));
69
+
70
+ -- Verification queries
71
+ SELECT 'chat_payments table created successfully!' as status;
72
+ SELECT COUNT(*) as payment_count FROM chat_payments;
73
+
74
+ -- Query to test: Get recent payments
75
+ -- SELECT
76
+ -- p.id,
77
+ -- sender.username as sender,
78
+ -- recipient.username as recipient,
79
+ -- p.amount_sol,
80
+ -- p.status,
81
+ -- p.transaction_signature,
82
+ -- p.created_at
83
+ -- FROM chat_payments p
84
+ -- JOIN users sender ON p.sender_user_id = sender.id
85
+ -- JOIN users recipient ON p.recipient_user_id = recipient.id
86
+ -- ORDER BY p.created_at DESC
87
+ -- LIMIT 10;
88
+
89
+
90
+
91
+
92
+
93
+
94
+
95
+
96
+
@@ -0,0 +1,22 @@
1
+ -- Add sports_event_id column to games table for ESPN game ID mapping
2
+ -- This allows us to link TheSportsDB games with ESPN live game data
3
+
4
+ -- Add the column (nullable since existing games won't have it)
5
+ ALTER TABLE games ADD COLUMN IF NOT EXISTS sports_event_id VARCHAR(50);
6
+
7
+ -- Create index for faster lookups
8
+ CREATE INDEX IF NOT EXISTS idx_games_sports_event_id ON games(sports_event_id);
9
+
10
+ -- Add comment
11
+ COMMENT ON COLUMN games.sports_event_id IS 'ESPN game ID for live game data integration';
12
+
13
+ SELECT 'sports_event_id column added successfully!' AS status;
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+