dubs-server 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +280 -0
- package/CLAUDE.md +46 -0
- package/CONNECT4_PRODUCTION_DEPLOY.md +155 -0
- package/CURRENT_SESSION.md +171 -0
- package/CURRENT_SESSION_DRAW.md +516 -0
- package/MARCH_MADNESS_SURVIVOR.md +254 -0
- package/PANDA.md +166 -0
- package/Procfile +4 -0
- package/README.md +476 -0
- package/controllers/livescoresController.js +376 -0
- package/controllers/pickemController.js +554 -0
- package/controllers/survivorAdminController.js +887 -0
- package/controllers/survivorController.js +623 -0
- package/cron/oracleMonitor.js +77 -0
- package/cron/pickemOracleMonitor.js +73 -0
- package/data/jackpot-history.json +952 -0
- package/data/ncaaTeams.js +406 -0
- package/documentation/API_SECURITY_GUIDE.md +327 -0
- package/documentation/ARCADE_API.md +593 -0
- package/documentation/ARCADE_IMPLEMENTATION_SUMMARY.md +399 -0
- package/documentation/ARCADE_QUICKSTART.md +242 -0
- package/documentation/AUTOMATIC_MODE_ORACLE.md +321 -0
- package/documentation/BUG_FIX_COHORT_DATE_DISPLAY.md +171 -0
- package/documentation/CLAIM_MIGRATION_INSTRUCTIONS.md +52 -0
- package/documentation/CLAIM_STATUS_FIX.md +67 -0
- package/documentation/CLI_TOOL_GUIDE.md +372 -0
- package/documentation/COHORT_RETENTION_ANALYSIS.md +295 -0
- package/documentation/COHORT_RETENTION_IMPLEMENTATION_COMPLETE.md +461 -0
- package/documentation/COHORT_RETENTION_SUMMARY.md +204 -0
- package/documentation/COMPLETE_PROJECT_SUMMARY.md +490 -0
- package/documentation/DATABASE_QUERIES.md +269 -0
- package/documentation/DATABASE_RETENTION_POLICY.md +390 -0
- package/documentation/DATABASE_SETUP_GUIDE.md +361 -0
- package/documentation/DATABASE_SETUP_SUMMARY.md +247 -0
- package/documentation/DEMO_API_CURL_COMMANDS.md +656 -0
- package/documentation/DEPLOYMENT_SUMMARY.txt +100 -0
- package/documentation/DUPLICATE_NOTIFICATIONS_FIXED.md +201 -0
- package/documentation/EXCHANGE_RATES_INTEGRATION.md +371 -0
- package/documentation/FINAL_API_PROTECTION_TABLE.md +175 -0
- package/documentation/GAME_START_NOTIFICATIONS_DEPLOYMENT.md +256 -0
- package/documentation/GAME_START_NOTIFICATIONS_INTEGRATION.md +275 -0
- package/documentation/HEROKU_DEPLOYMENT.md +134 -0
- package/documentation/HEROKU_SCHEDULER_SETUP.md +271 -0
- package/documentation/JACKPOT_API.md +521 -0
- package/documentation/JACKPOT_DEPLOYMENT_GUIDE.md +362 -0
- package/documentation/JWT_IMPLEMENTATION_SUMMARY.md +373 -0
- package/documentation/JWT_QUICK_SETUP.md +268 -0
- package/documentation/JWT_TESTING_GUIDE.md +404 -0
- package/documentation/KEEPER_RECOVERY_GUIDE.md +381 -0
- package/documentation/KEEPER_SETUP.md +206 -0
- package/documentation/KEEPER_STATE_MACHINE.md +423 -0
- package/documentation/LATEST_PRODUCTION_SETUP.md +387 -0
- package/documentation/LOCAL_VOTING_TEST.md +279 -0
- package/documentation/ORACLE_FIXES_SUMMARY.md +188 -0
- package/documentation/ORACLE_POSTGRESQL_UPDATE.md +202 -0
- package/documentation/PAYMENT_DEPLOYMENT.md +209 -0
- package/documentation/PNL_TRACKING_SETUP.md +189 -0
- package/documentation/PREVENTING_LOCKUP_ERRORS.md +472 -0
- package/documentation/PRODUCTION_READY_SUMMARY.md +227 -0
- package/documentation/PUBLIC_VS_PRIVATE_ENDPOINTS.md +278 -0
- package/documentation/QUICK_AUTH_SETUP.md +99 -0
- package/documentation/QUICK_DEPLOY.md +224 -0
- package/documentation/QUICK_FIX.md +114 -0
- package/documentation/QUICK_START.md +152 -0
- package/documentation/REFEREE_MODE_GUIDE.md +392 -0
- package/documentation/RETENTION_CORE_ACTION_UPDATE.md +313 -0
- package/documentation/RETENTION_UPDATE_SUMMARY.md +108 -0
- package/documentation/RUN_MIGRATION_NOW.md +39 -0
- package/documentation/SCRIPTS_UPDATE_SUMMARY.md +251 -0
- package/documentation/SETUP_GUIDE.md +184 -0
- package/documentation/STATE_MACHINE_IMPLEMENTATION.md +250 -0
- package/documentation/TELEGRAM_NOTIFICATIONS_DIAGNOSIS.md +361 -0
- package/documentation/UNIFIED_ARCHITECTURE.md +231 -0
- package/documentation/VOTING_DEPLOYMENT_SUMMARY.md +392 -0
- package/documentation/WEBSOCKET_ARCHITECTURE.md +881 -0
- package/documentation/WHAT_WE_BUILT_TODAY.md +369 -0
- package/documentation/latest/LATEST_PRODUCTION_SETUP.md +865 -0
- package/ecosystem.config.js +65 -0
- package/env.template +125 -0
- package/middleware/apiKeyAuth.js +136 -0
- package/middleware/authenticate.js +214 -0
- package/middleware/developerUserAuth.js +76 -0
- package/middleware/socketAuth.js +69 -0
- package/package.json +49 -0
- package/postman/Dubs-API-v1-With-Voting.postman_collection.json +555 -0
- package/postman/Dubs-API-v1.postman_collection.json +205 -0
- package/postman/Dubs_Developer_API.postman_collection.json +662 -0
- package/postman/QUICKSTART.md +118 -0
- package/postman/QUICK_REFERENCE.md +246 -0
- package/postman/README.md +71 -0
- package/postman/VOTING_API_GUIDE.md +426 -0
- package/refactor/Animations.md +148 -0
- package/refactor/Chat.md +252 -0
- package/routes/actionsRoutes.js +699 -0
- package/routes/adminRoutes.js +370 -0
- package/routes/analyticsRoutes.js +1262 -0
- package/routes/arcadeRoutes.js +557 -0
- package/routes/authRoutes.js +2310 -0
- package/routes/avatarRoutes.js +85 -0
- package/routes/botRoutes.js +211 -0
- package/routes/chatRoutes.js +377 -0
- package/routes/cryptoPriceRoutes.js +105 -0
- package/routes/developerRoutes.js +4201 -0
- package/routes/deviceRoutes.js +214 -0
- package/routes/dmRoutes.js +167 -0
- package/routes/esportsRoutes.js +806 -0
- package/routes/exchangeRateRoutes.js +233 -0
- package/routes/gamesRoutes.js +3028 -0
- package/routes/jackpotRoutes.js +754 -0
- package/routes/keeperMonitoringRoutes.js +156 -0
- package/routes/keeperWebhookRoutes.js +466 -0
- package/routes/livescoresRoutes.js +31 -0
- package/routes/pickemAdminRoutes.js +199 -0
- package/routes/pickemRoutes.js +231 -0
- package/routes/playerStatsRoutes.js +147 -0
- package/routes/portfolioRoutes.js +217 -0
- package/routes/promoRoutes.js +418 -0
- package/routes/referralEarningsRoutes.js +392 -0
- package/routes/socialRoutes.js +459 -0
- package/routes/sportsRoutes.js +1271 -0
- package/routes/survivorAdminRoutes.js +345 -0
- package/routes/survivorRoutes.js +756 -0
- package/routes/uploadRoutes.js +256 -0
- package/routes/userProfileRoutes.js +244 -0
- package/routes/whatsNewRoutes.js +331 -0
- package/scripts/.claude/settings.local.json +15 -0
- package/scripts/README.md +170 -0
- package/scripts/RESTART_EVERYTHING.sh +104 -0
- package/scripts/add-claim-columns.sql +48 -0
- package/scripts/add-crypto-prices-cache.sql +27 -0
- package/scripts/add-exchange-rates-cache.sql +40 -0
- package/scripts/add-game-invite-column.sql +23 -0
- package/scripts/add-game-invite-notification.sql +33 -0
- package/scripts/add-game-invite-telegram-pref.sql +16 -0
- package/scripts/add-game-joined-notification.sql +16 -0
- package/scripts/add-game-joined-pref.js +40 -0
- package/scripts/add-game-joined-preference.sql +6 -0
- package/scripts/add-game-start-notifications.sql +41 -0
- package/scripts/add-notification-flags-to-games.sql +55 -0
- package/scripts/add-pending-game-dismissals.sql +19 -0
- package/scripts/add-preferred-currency.sql +34 -0
- package/scripts/add-winner-columns.js +61 -0
- package/scripts/add_mention_system.sql +53 -0
- package/scripts/add_payment_system.sql +96 -0
- package/scripts/add_sports_event_id_column.sql +22 -0
- package/scripts/analyze-cohort-data-heroku.js +276 -0
- package/scripts/analyze-cohort-data.js +295 -0
- package/scripts/analyze-prod-cohorts.sh +10 -0
- package/scripts/backfill-matchup-images.js +245 -0
- package/scripts/backfill-missing-signatures.js +175 -0
- package/scripts/backfill-referral-earnings.js +202 -0
- package/scripts/check-chat-schema.js +130 -0
- package/scripts/check-db.sh +14 -0
- package/scripts/check_oracle_in_game.js +54 -0
- package/scripts/cleanup-database.js +193 -0
- package/scripts/clear-notification-cache.js +85 -0
- package/scripts/convert-mnemonic.js +50 -0
- package/scripts/create-users-table.sql +44 -0
- package/scripts/debug-cohort-counts.js +248 -0
- package/scripts/debug-winner-calc.js +84 -0
- package/scripts/deploy-payment-system.sh +118 -0
- package/scripts/deploy-to-heroku.sh +63 -0
- package/scripts/diagnose-locked-round.js +143 -0
- package/scripts/dubs-cli.js +720 -0
- package/scripts/dump-account.js +65 -0
- package/scripts/find-vrf-offset.js +48 -0
- package/scripts/fix-chat-notifications-constraint.sql +122 -0
- package/scripts/fix-claim-columns.js +124 -0
- package/scripts/fix-constraint-now.js +44 -0
- package/scripts/fix-lock-timestamps.js +96 -0
- package/scripts/fix-locked-round.sh +126 -0
- package/scripts/fix-missing-badges.sql +91 -0
- package/scripts/fix-payment-notifications.sql +41 -0
- package/scripts/force-new-round.js +55 -0
- package/scripts/force-resolve-and-claim.js +278 -0
- package/scripts/important/README.md +115 -0
- package/scripts/important/authority-force-lock.js +197 -0
- package/scripts/important/authority-resolve-game.js +267 -0
- package/scripts/important/check-game-status.js +373 -0
- package/scripts/important/list-pending-games-by-version.js +270 -0
- package/scripts/important/reconcile-v1-v2-payouts.js +270 -0
- package/scripts/initialize-jackpot.js +111 -0
- package/scripts/jackpot/.claude/settings.local.json +10 -0
- package/scripts/jackpot/force-reset.js +84 -0
- package/scripts/jackpot/initialize-mainnet.js +100 -0
- package/scripts/jackpot/keeper.js +742 -0
- package/scripts/jackpot/status.js +107 -0
- package/scripts/jackpot/update-round-duration.js +143 -0
- package/scripts/keeper-bot.js +112 -0
- package/scripts/list-pending-games.js +131 -0
- package/scripts/migrate-chat-v2.js +127 -0
- package/scripts/migrate-chat-winners.js +84 -0
- package/scripts/migrate-chat.sh +17 -0
- package/scripts/migrate-game-invite.js +83 -0
- package/scripts/migrate-heroku-game-notifications.sh +159 -0
- package/scripts/migrations/001_analytics_tables.sql +422 -0
- package/scripts/migrations/002_add_matchup_image_url.sql +14 -0
- package/scripts/migrations/003_referral_earnings.sql +208 -0
- package/scripts/migrations/004_add_whats_new_notification_type.sql +62 -0
- package/scripts/migrations/005_add_connect4_your_turn_notification.sql +61 -0
- package/scripts/migrations/005_push_notifications.sql +55 -0
- package/scripts/migrations/006_add_draw_team_players.sql +28 -0
- package/scripts/migrations/006_add_game_cancelled_notification.sql +62 -0
- package/scripts/migrations/007_add_gif_url.sql +8 -0
- package/scripts/migrations/008_add_connect4_columns.sql +139 -0
- package/scripts/migrations/008_add_pool_tracking.sql +22 -0
- package/scripts/migrations/009_create_survivor_pool_tables.sql +174 -0
- package/scripts/migrations/010_add_survivor_pool_outcome.sql +28 -0
- package/scripts/migrations/011_create_developer_tables.sql +67 -0
- package/scripts/migrations/011_fix_keeper_tables.sql +85 -0
- package/scripts/migrations/012_create_developer_webhooks.sql +31 -0
- package/scripts/migrations/013_add_network_mode.sql +18 -0
- package/scripts/migrations/014_create_developer_app_users.sql +19 -0
- package/scripts/migrations/015_add_ui_config.sql +4 -0
- package/scripts/migrations/016_add_resolution_secret.sql +4 -0
- package/scripts/migrations/017_add_external_game_id.sql +3 -0
- package/scripts/migrations/018_create_pickem_tables.sql +115 -0
- package/scripts/migrations/019_expo_push_tokens.sql +19 -0
- package/scripts/migrations/create_whats_new_tables.sql +88 -0
- package/scripts/migrations/drop_live_games_tables.sql +34 -0
- package/scripts/open-jackpot-round.js +85 -0
- package/scripts/purge-all-data.sh +329 -0
- package/scripts/purge-all-data.sql +142 -0
- package/scripts/purge-heroku-data.sh +149 -0
- package/scripts/purge-heroku-data.sql +62 -0
- package/scripts/rebuild-heroku-database.sh +113 -0
- package/scripts/recover-funds.js +357 -0
- package/scripts/regenerate-epl-images.js +278 -0
- package/scripts/resize-s3-matchup-images.js +374 -0
- package/scripts/resolve-direct.js +88 -0
- package/scripts/resolve-mock-game.js +124 -0
- package/scripts/resolve-pickem-game.js +55 -0
- package/scripts/resolve-round-manual.js +83 -0
- package/scripts/resolve-stuck-game.js +382 -0
- package/scripts/resolve-stuck-round.js +42 -0
- package/scripts/run-connect4-migration.sh +16 -0
- package/scripts/run-mention-migration.sh +32 -0
- package/scripts/run-payment-migration.sh +51 -0
- package/scripts/run-preferred-currency-migration.sh +31 -0
- package/scripts/run-referral-earnings-migration.sh +32 -0
- package/scripts/run-survivor-outcome-migration.sh +16 -0
- package/scripts/seed-test-users.js +346 -0
- package/scripts/setup-auth-tables.js +78 -0
- package/scripts/setup-complete-database.sql +992 -0
- package/scripts/setup-database-fresh.sh +359 -0
- package/scripts/setup-heroku-keeper.sh +48 -0
- package/scripts/setup-keeper-database.js +83 -0
- package/scripts/setup-keeper-state-db.sql +110 -0
- package/scripts/setup-oracle.sh +39 -0
- package/scripts/setup-pnl-tracking.js +111 -0
- package/scripts/start-devnet.sh +14 -0
- package/scripts/test-arcade-devnet.sh +160 -0
- package/scripts/test-arcade-match.sh +109 -0
- package/scripts/test-automatic-mode.sh +239 -0
- package/scripts/test-connect4-cancel-claim.js +370 -0
- package/scripts/test-connect4-e2e.js +369 -0
- package/scripts/test-connect4-resolve.js +369 -0
- package/scripts/test-game-state-endpoint.js +136 -0
- package/scripts/test-invite-notification.js +86 -0
- package/scripts/test-jackpot-api.sh +71 -0
- package/scripts/test-poll-confirmation.js +267 -0
- package/scripts/test-resolve-game.js +271 -0
- package/scripts/test-resolve-signature.js +223 -0
- package/scripts/test-signature-preservation.js +124 -0
- package/scripts/test-state-machine.js +291 -0
- package/scripts/test-webhook-receiver.js +60 -0
- package/scripts/update-notification-constraint.js +52 -0
- package/scripts/verify-account-layout.js +145 -0
- package/scripts/verify-winner-algorithm.js +278 -0
- package/server.js +5259 -0
- package/services/arcadeMatchService.js +763 -0
- package/services/automaticGameOracle.js +1596 -0
- package/services/chatService.js +1612 -0
- package/services/connect4GameService.js +1049 -0
- package/services/connect4NotificationService.js +374 -0
- package/services/cryptoPriceService.js +223 -0
- package/services/customGameResolver.js +260 -0
- package/services/db.js +79 -0
- package/services/directMessageService.js +389 -0
- package/services/discordNotifications.js +160 -0
- package/services/exchangeRateService.js +289 -0
- package/services/expoPushService.js +314 -0
- package/services/gamesCacheService.js +539 -0
- package/services/jackpotHistory.js +331 -0
- package/services/jackpotService.js +856 -0
- package/services/keeperStateService.js +355 -0
- package/services/matchupImageService.js +591 -0
- package/services/notificationCacheService.js +407 -0
- package/services/pickemOracle.js +440 -0
- package/services/playerStatsService.js +389 -0
- package/services/portfolioService.js +555 -0
- package/services/promoService.js +757 -0
- package/services/promoTreasuryService.js +239 -0
- package/services/pushNotifications.js +353 -0
- package/services/redisService.js +422 -0
- package/services/referralEarningsService.js +728 -0
- package/services/s3Service.js +396 -0
- package/services/socialService.js +1202 -0
- package/services/survivorOracle.js +469 -0
- package/services/survivorSimulator.js +475 -0
- package/services/telegramNotifications.js +461 -0
- package/services/userProfileStatsService.js +1185 -0
- package/services/whatsNewService.js +388 -0
- package/utils/urlHelper.js +95 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seed script to generate 100 test users with different game interests
|
|
3
|
+
* Run with: node scripts/seed-test-users.js
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { Pool } = require('pg');
|
|
7
|
+
|
|
8
|
+
const pool = new Pool({
|
|
9
|
+
connectionString: process.env.DATABASE_URL || 'postgresql://adamdahan@localhost:5432/dubs_db',
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
// Sample data for generating users
|
|
13
|
+
const FIRST_NAMES = [
|
|
14
|
+
'Alex', 'Jordan', 'Taylor', 'Morgan', 'Casey', 'Riley', 'Quinn', 'Avery',
|
|
15
|
+
'Blake', 'Cameron', 'Dakota', 'Drew', 'Ellis', 'Finley', 'Gray', 'Harper',
|
|
16
|
+
'Jaden', 'Kai', 'Lane', 'Max', 'Noah', 'Parker', 'Reese', 'Sage', 'Skyler',
|
|
17
|
+
'Tyler', 'Val', 'Wren', 'Zion', 'River', 'Phoenix', 'Storm', 'Ash', 'Bay'
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const LAST_NAMES = [
|
|
21
|
+
'Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',
|
|
22
|
+
'Rodriguez', 'Martinez', 'Hernandez', 'Lopez', 'Gonzalez', 'Wilson', 'Anderson',
|
|
23
|
+
'Thomas', 'Taylor', 'Moore', 'Jackson', 'Martin', 'Lee', 'Perez', 'Thompson',
|
|
24
|
+
'White', 'Harris', 'Sanchez', 'Clark', 'Ramirez', 'Lewis', 'Robinson'
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const SUFFIXES = ['_sol', '_crypto', '_degen', '_wagr', '_bet', '_play', '_game', '_pro', '_dev', ''];
|
|
28
|
+
|
|
29
|
+
// Sports events for creating games
|
|
30
|
+
const SPORTS_EVENTS = {
|
|
31
|
+
NBA: [
|
|
32
|
+
{ home: 'Lakers', away: 'Celtics', league: 'NBA' },
|
|
33
|
+
{ home: 'Warriors', away: 'Heat', league: 'NBA' },
|
|
34
|
+
{ home: 'Bulls', away: 'Knicks', league: 'NBA' },
|
|
35
|
+
{ home: 'Nets', away: 'Suns', league: 'NBA' },
|
|
36
|
+
{ home: 'Bucks', away: 'Sixers', league: 'NBA' },
|
|
37
|
+
],
|
|
38
|
+
NHL: [
|
|
39
|
+
{ home: 'Bruins', away: 'Rangers', league: 'NHL' },
|
|
40
|
+
{ home: 'Maple Leafs', away: 'Canadiens', league: 'NHL' },
|
|
41
|
+
{ home: 'Penguins', away: 'Capitals', league: 'NHL' },
|
|
42
|
+
{ home: 'Lightning', away: 'Panthers', league: 'NHL' },
|
|
43
|
+
],
|
|
44
|
+
NFL: [
|
|
45
|
+
{ home: 'Chiefs', away: 'Eagles', league: 'NFL' },
|
|
46
|
+
{ home: 'Bills', away: 'Cowboys', league: 'NFL' },
|
|
47
|
+
{ home: '49ers', away: 'Dolphins', league: 'NFL' },
|
|
48
|
+
{ home: 'Ravens', away: 'Lions', league: 'NFL' },
|
|
49
|
+
],
|
|
50
|
+
EPL: [
|
|
51
|
+
{ home: 'Liverpool', away: 'Man City', league: 'English Premier League' },
|
|
52
|
+
{ home: 'Arsenal', away: 'Chelsea', league: 'English Premier League' },
|
|
53
|
+
{ home: 'Man United', away: 'Tottenham', league: 'English Premier League' },
|
|
54
|
+
],
|
|
55
|
+
UFC: [
|
|
56
|
+
{ home: 'Fighter A', away: 'Fighter B', league: 'UFC' },
|
|
57
|
+
{ home: 'Fighter C', away: 'Fighter D', league: 'UFC' },
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Generate a random wallet address
|
|
62
|
+
function generateWalletAddress() {
|
|
63
|
+
const chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
|
64
|
+
let result = '';
|
|
65
|
+
for (let i = 0; i < 44; i++) {
|
|
66
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Generate a unique username
|
|
72
|
+
function generateUsername(index) {
|
|
73
|
+
const firstName = FIRST_NAMES[Math.floor(Math.random() * FIRST_NAMES.length)];
|
|
74
|
+
const lastName = LAST_NAMES[Math.floor(Math.random() * LAST_NAMES.length)];
|
|
75
|
+
const suffix = SUFFIXES[Math.floor(Math.random() * SUFFIXES.length)];
|
|
76
|
+
const num = Math.floor(Math.random() * 100);
|
|
77
|
+
return `${firstName}${lastName}${num}${suffix}`.toLowerCase().slice(0, 20);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Generate a random avatar URL using DiceBear
|
|
81
|
+
function generateAvatar(index) {
|
|
82
|
+
const styles = ['adventurer', 'avataaars', 'bottts', 'fun-emoji', 'lorelei', 'micah', 'miniavs', 'personas'];
|
|
83
|
+
const style = styles[Math.floor(Math.random() * styles.length)];
|
|
84
|
+
return `https://api.dicebear.com/7.x/${style}/svg?seed=${index}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Generate a game ID
|
|
88
|
+
function generateGameId(type, index) {
|
|
89
|
+
return `test-${type}-${Date.now()}-${index}`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function seedTestUsers() {
|
|
93
|
+
const client = await pool.connect();
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
console.log('š± Starting seed script...\n');
|
|
97
|
+
|
|
98
|
+
await client.query('BEGIN');
|
|
99
|
+
|
|
100
|
+
// 1. Create test games for each category
|
|
101
|
+
console.log('š¦ Creating test games...');
|
|
102
|
+
const gameIds = {
|
|
103
|
+
NBA: [],
|
|
104
|
+
NHL: [],
|
|
105
|
+
NFL: [],
|
|
106
|
+
EPL: [],
|
|
107
|
+
UFC: [],
|
|
108
|
+
connect4: [],
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// Create sports games
|
|
112
|
+
for (const [category, events] of Object.entries(SPORTS_EVENTS)) {
|
|
113
|
+
for (let i = 0; i < events.length; i++) {
|
|
114
|
+
const event = events[i];
|
|
115
|
+
const gameId = generateGameId(category.toLowerCase(), i);
|
|
116
|
+
const gameAddress = generateWalletAddress();
|
|
117
|
+
|
|
118
|
+
await client.query(`
|
|
119
|
+
INSERT INTO games (game_id, game_address, title, game_type, created_by, sports_event, is_resolved, created_at)
|
|
120
|
+
VALUES ($1, $2, $3, 'sports', $4, $5, true, NOW() - interval '${Math.floor(Math.random() * 30)} days')
|
|
121
|
+
ON CONFLICT (game_id) DO NOTHING
|
|
122
|
+
`, [
|
|
123
|
+
gameId,
|
|
124
|
+
gameAddress,
|
|
125
|
+
`${event.home} vs ${event.away}`,
|
|
126
|
+
generateWalletAddress(),
|
|
127
|
+
JSON.stringify({
|
|
128
|
+
strLeague: event.league,
|
|
129
|
+
strHomeTeam: event.home,
|
|
130
|
+
strAwayTeam: event.away,
|
|
131
|
+
strSport: category === 'EPL' ? 'Soccer' : category === 'NHL' ? 'Ice Hockey' : category === 'NFL' ? 'American Football' : category === 'UFC' ? 'Fighting' : 'Basketball',
|
|
132
|
+
}),
|
|
133
|
+
]);
|
|
134
|
+
|
|
135
|
+
gameIds[category].push(gameId);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Create connect4 games
|
|
140
|
+
for (let i = 0; i < 5; i++) {
|
|
141
|
+
const gameId = generateGameId('connect4', i);
|
|
142
|
+
const gameAddress = generateWalletAddress();
|
|
143
|
+
|
|
144
|
+
await client.query(`
|
|
145
|
+
INSERT INTO games (game_id, game_address, title, game_type, created_by, is_resolved, created_at)
|
|
146
|
+
VALUES ($1, $2, 'Connect4 Game', 'connect4', $3, true, NOW() - interval '${Math.floor(Math.random() * 30)} days')
|
|
147
|
+
ON CONFLICT (game_id) DO NOTHING
|
|
148
|
+
`, [gameId, gameAddress, generateWalletAddress()]);
|
|
149
|
+
|
|
150
|
+
gameIds.connect4.push(gameId);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
console.log(` Created ${Object.values(gameIds).flat().length} test games\n`);
|
|
154
|
+
|
|
155
|
+
// 2. Create 100 test users with different interests
|
|
156
|
+
console.log('š„ Creating 100 test users...');
|
|
157
|
+
|
|
158
|
+
const users = [];
|
|
159
|
+
const usedUsernames = new Set();
|
|
160
|
+
|
|
161
|
+
for (let i = 0; i < 100; i++) {
|
|
162
|
+
let username = generateUsername(i);
|
|
163
|
+
while (usedUsernames.has(username)) {
|
|
164
|
+
username = generateUsername(i) + Math.floor(Math.random() * 1000);
|
|
165
|
+
}
|
|
166
|
+
usedUsernames.add(username);
|
|
167
|
+
|
|
168
|
+
const walletAddress = generateWalletAddress();
|
|
169
|
+
const avatar = generateAvatar(i);
|
|
170
|
+
|
|
171
|
+
const result = await client.query(`
|
|
172
|
+
INSERT INTO users (wallet_address, username, avatar, created_at)
|
|
173
|
+
VALUES ($1, $2, $3, NOW() - interval '${Math.floor(Math.random() * 60)} days')
|
|
174
|
+
ON CONFLICT (wallet_address) DO UPDATE SET username = EXCLUDED.username
|
|
175
|
+
RETURNING id, wallet_address, username
|
|
176
|
+
`, [walletAddress, username, avatar]);
|
|
177
|
+
|
|
178
|
+
users.push(result.rows[0]);
|
|
179
|
+
|
|
180
|
+
if ((i + 1) % 20 === 0) {
|
|
181
|
+
console.log(` Created ${i + 1}/100 users...`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
console.log(` Created ${users.length} test users\n`);
|
|
186
|
+
|
|
187
|
+
// 3. Assign users to games with different interest distributions
|
|
188
|
+
console.log('š® Assigning users to games (creating interests)...');
|
|
189
|
+
|
|
190
|
+
// Interest distribution:
|
|
191
|
+
// - 30% NBA fans (some overlap with other sports)
|
|
192
|
+
// - 25% NHL fans
|
|
193
|
+
// - 25% NFL fans
|
|
194
|
+
// - 20% Soccer (EPL) fans
|
|
195
|
+
// - 15% UFC fans
|
|
196
|
+
// - 20% Connect4 players
|
|
197
|
+
// - 15% will have no games (new users)
|
|
198
|
+
|
|
199
|
+
let gameRefsCreated = 0;
|
|
200
|
+
|
|
201
|
+
for (let i = 0; i < users.length; i++) {
|
|
202
|
+
const user = users[i];
|
|
203
|
+
const rand = Math.random();
|
|
204
|
+
|
|
205
|
+
// 15% of users are "new" with no game history
|
|
206
|
+
if (rand < 0.15) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Randomly assign interests
|
|
211
|
+
const interests = [];
|
|
212
|
+
|
|
213
|
+
if (Math.random() < 0.30) interests.push('NBA');
|
|
214
|
+
if (Math.random() < 0.25) interests.push('NHL');
|
|
215
|
+
if (Math.random() < 0.25) interests.push('NFL');
|
|
216
|
+
if (Math.random() < 0.20) interests.push('EPL');
|
|
217
|
+
if (Math.random() < 0.15) interests.push('UFC');
|
|
218
|
+
if (Math.random() < 0.20) interests.push('connect4');
|
|
219
|
+
|
|
220
|
+
// Ensure at least one interest if not a "new" user
|
|
221
|
+
if (interests.length === 0) {
|
|
222
|
+
const categories = ['NBA', 'NHL', 'NFL', 'EPL', 'UFC', 'connect4'];
|
|
223
|
+
interests.push(categories[Math.floor(Math.random() * categories.length)]);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Create game refs for each interest
|
|
227
|
+
for (const interest of interests) {
|
|
228
|
+
const categoryGames = gameIds[interest];
|
|
229
|
+
// Join 1-3 random games in each category
|
|
230
|
+
const numGames = Math.min(Math.floor(Math.random() * 3) + 1, categoryGames.length);
|
|
231
|
+
const shuffledGames = [...categoryGames].sort(() => Math.random() - 0.5);
|
|
232
|
+
|
|
233
|
+
for (let j = 0; j < numGames; j++) {
|
|
234
|
+
const gameId = shuffledGames[j];
|
|
235
|
+
const daysAgo = Math.floor(Math.random() * 30);
|
|
236
|
+
|
|
237
|
+
await client.query(`
|
|
238
|
+
INSERT INTO user_game_refs (wallet_address, game_id, role, team_choice, joined_at, created_at)
|
|
239
|
+
VALUES ($1, $2, 'player', $3, NOW() - interval '${daysAgo} days', NOW() - interval '${daysAgo} days')
|
|
240
|
+
ON CONFLICT (wallet_address, game_id) DO NOTHING
|
|
241
|
+
`, [user.wallet_address, gameId, Math.random() > 0.5 ? 'home' : 'away']);
|
|
242
|
+
|
|
243
|
+
gameRefsCreated++;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
console.log(` Created ${gameRefsCreated} game participation records\n`);
|
|
249
|
+
|
|
250
|
+
// 4. Create sports_betting_stats for some users (top players)
|
|
251
|
+
console.log('š Creating sports betting stats (for Top Players)...');
|
|
252
|
+
|
|
253
|
+
// Pick random users to be "top players" with wins
|
|
254
|
+
const topSportsPlayers = users.slice(0, 20); // First 20 users get sports stats
|
|
255
|
+
for (let i = 0; i < topSportsPlayers.length; i++) {
|
|
256
|
+
const user = topSportsPlayers[i];
|
|
257
|
+
const wins = Math.floor(Math.random() * 15) + 1; // 1-15 wins
|
|
258
|
+
const losses = Math.floor(Math.random() * 10); // 0-9 losses
|
|
259
|
+
const totalWagered = (wins + losses) * (Math.random() * 0.5 + 0.1); // Random SOL wagered
|
|
260
|
+
const totalWon = wins * (Math.random() * 0.8 + 0.2);
|
|
261
|
+
|
|
262
|
+
await client.query(`
|
|
263
|
+
INSERT INTO sports_betting_stats (
|
|
264
|
+
wallet_address, games_created, games_joined, games_won, games_lost,
|
|
265
|
+
total_wagered_sol, total_won_sol, net_pnl_sol, last_played_at
|
|
266
|
+
)
|
|
267
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, NOW() - interval '${Math.floor(Math.random() * 7)} days')
|
|
268
|
+
ON CONFLICT (wallet_address) DO UPDATE SET
|
|
269
|
+
games_won = EXCLUDED.games_won,
|
|
270
|
+
games_lost = EXCLUDED.games_lost,
|
|
271
|
+
total_wagered_sol = EXCLUDED.total_wagered_sol,
|
|
272
|
+
total_won_sol = EXCLUDED.total_won_sol
|
|
273
|
+
`, [
|
|
274
|
+
user.wallet_address,
|
|
275
|
+
Math.floor(Math.random() * 5),
|
|
276
|
+
wins + losses,
|
|
277
|
+
wins,
|
|
278
|
+
losses,
|
|
279
|
+
totalWagered.toFixed(4),
|
|
280
|
+
totalWon.toFixed(4),
|
|
281
|
+
(totalWon - totalWagered).toFixed(4)
|
|
282
|
+
]);
|
|
283
|
+
}
|
|
284
|
+
console.log(` Created sports stats for ${topSportsPlayers.length} users\n`);
|
|
285
|
+
|
|
286
|
+
// 5. Update some connect4 games to have winners
|
|
287
|
+
console.log('š“ Updating connect4 games with winners...');
|
|
288
|
+
const connect4Games = gameIds.connect4;
|
|
289
|
+
for (const gameId of connect4Games) {
|
|
290
|
+
const winner = Math.random() > 0.5 ? 'red' : 'yellow';
|
|
291
|
+
await client.query(`
|
|
292
|
+
UPDATE games SET connect4_winner = $1, is_resolved = true WHERE game_id = $2
|
|
293
|
+
`, [winner, gameId]);
|
|
294
|
+
}
|
|
295
|
+
console.log(` Updated ${connect4Games.length} connect4 games with winners\n`);
|
|
296
|
+
|
|
297
|
+
await client.query('COMMIT');
|
|
298
|
+
|
|
299
|
+
// 4. Print summary
|
|
300
|
+
console.log('š Summary:');
|
|
301
|
+
|
|
302
|
+
const categoryCounts = await client.query(`
|
|
303
|
+
WITH category_counts AS (
|
|
304
|
+
SELECT
|
|
305
|
+
CASE
|
|
306
|
+
WHEN g.game_type = 'connect4' THEN 'connect4'
|
|
307
|
+
WHEN g.sports_event->>'strLeague' = 'NBA' THEN 'NBA'
|
|
308
|
+
WHEN g.sports_event->>'strLeague' = 'NHL' THEN 'NHL'
|
|
309
|
+
WHEN g.sports_event->>'strLeague' = 'NFL' THEN 'NFL'
|
|
310
|
+
WHEN g.sports_event->>'strLeague' = 'UFC' THEN 'UFC'
|
|
311
|
+
WHEN g.sports_event->>'strLeague' = 'English Premier League' THEN 'EPL'
|
|
312
|
+
ELSE NULL
|
|
313
|
+
END as category,
|
|
314
|
+
COUNT(DISTINCT ugr.wallet_address) as user_count
|
|
315
|
+
FROM user_game_refs ugr
|
|
316
|
+
JOIN games g ON g.game_id = ugr.game_id
|
|
317
|
+
GROUP BY 1
|
|
318
|
+
)
|
|
319
|
+
SELECT category, user_count FROM category_counts WHERE category IS NOT NULL ORDER BY user_count DESC
|
|
320
|
+
`);
|
|
321
|
+
|
|
322
|
+
const newUsersCount = await client.query(`
|
|
323
|
+
SELECT COUNT(*) as count FROM users u
|
|
324
|
+
WHERE NOT EXISTS (SELECT 1 FROM user_game_refs ugr WHERE ugr.wallet_address = u.wallet_address)
|
|
325
|
+
`);
|
|
326
|
+
|
|
327
|
+
console.log(' Users by interest:');
|
|
328
|
+
for (const row of categoryCounts.rows) {
|
|
329
|
+
const emoji = { NBA: 'š', NHL: 'š', NFL: 'š', EPL: 'ā½', UFC: 'š„', connect4: 'š“' }[row.category] || 'ā';
|
|
330
|
+
console.log(` ${emoji} ${row.category}: ${row.user_count} users`);
|
|
331
|
+
}
|
|
332
|
+
console.log(` š New Users (no games): ${newUsersCount.rows[0].count} users`);
|
|
333
|
+
|
|
334
|
+
console.log('\nā
Seed complete! Refresh your Social page to see the users.');
|
|
335
|
+
|
|
336
|
+
} catch (error) {
|
|
337
|
+
await client.query('ROLLBACK');
|
|
338
|
+
console.error('ā Error seeding database:', error);
|
|
339
|
+
throw error;
|
|
340
|
+
} finally {
|
|
341
|
+
client.release();
|
|
342
|
+
await pool.end();
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
seedTestUsers().catch(console.error);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Setup auth tables in Postgres
|
|
3
|
+
* Run with: node scripts/setup-auth-tables.js
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { Client } = require('pg');
|
|
7
|
+
require('dotenv').config();
|
|
8
|
+
|
|
9
|
+
const DATABASE_URL = process.env.DATABASE_URL;
|
|
10
|
+
|
|
11
|
+
if (!DATABASE_URL) {
|
|
12
|
+
console.error('ā DATABASE_URL environment variable not set');
|
|
13
|
+
console.log(' Add it to your .env file or set it in your environment');
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function setupTables() {
|
|
18
|
+
const client = new Client({
|
|
19
|
+
connectionString: DATABASE_URL,
|
|
20
|
+
ssl: DATABASE_URL.includes('amazonaws') || DATABASE_URL.includes('heroku')
|
|
21
|
+
? { rejectUnauthorized: false }
|
|
22
|
+
: undefined
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
await client.connect();
|
|
27
|
+
console.log('ā
Connected to database');
|
|
28
|
+
|
|
29
|
+
// Create users table
|
|
30
|
+
await client.query(`
|
|
31
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
32
|
+
id SERIAL PRIMARY KEY,
|
|
33
|
+
wallet_address VARCHAR(44) UNIQUE NOT NULL,
|
|
34
|
+
email VARCHAR(255),
|
|
35
|
+
username VARCHAR(50) NOT NULL,
|
|
36
|
+
avatar TEXT,
|
|
37
|
+
referral_code VARCHAR(50),
|
|
38
|
+
signature TEXT,
|
|
39
|
+
onboarding_complete BOOLEAN DEFAULT false,
|
|
40
|
+
created_at TIMESTAMP DEFAULT NOW(),
|
|
41
|
+
updated_at TIMESTAMP DEFAULT NOW()
|
|
42
|
+
);
|
|
43
|
+
`);
|
|
44
|
+
console.log('ā
Created users table');
|
|
45
|
+
|
|
46
|
+
// Create auth_nonces table
|
|
47
|
+
await client.query(`
|
|
48
|
+
CREATE TABLE IF NOT EXISTS auth_nonces (
|
|
49
|
+
wallet_address VARCHAR(44) PRIMARY KEY,
|
|
50
|
+
nonce VARCHAR(64) NOT NULL,
|
|
51
|
+
expires_at TIMESTAMP NOT NULL,
|
|
52
|
+
used BOOLEAN DEFAULT false,
|
|
53
|
+
created_at TIMESTAMP DEFAULT NOW()
|
|
54
|
+
);
|
|
55
|
+
`);
|
|
56
|
+
console.log('ā
Created auth_nonces table');
|
|
57
|
+
|
|
58
|
+
// Create indexes
|
|
59
|
+
await client.query('CREATE INDEX IF NOT EXISTS idx_users_wallet ON users(wallet_address)');
|
|
60
|
+
await client.query('CREATE INDEX IF NOT EXISTS idx_users_username ON users(username)');
|
|
61
|
+
await client.query('CREATE INDEX IF NOT EXISTS idx_nonces_expires ON auth_nonces(expires_at)');
|
|
62
|
+
console.log('ā
Created indexes');
|
|
63
|
+
|
|
64
|
+
console.log('\nš Auth tables setup complete!');
|
|
65
|
+
console.log('\nTables created:');
|
|
66
|
+
console.log(' - users (user profiles)');
|
|
67
|
+
console.log(' - auth_nonces (signature verification)');
|
|
68
|
+
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error('ā Error setting up tables:', error.message);
|
|
71
|
+
process.exit(1);
|
|
72
|
+
} finally {
|
|
73
|
+
await client.end();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
setupTables();
|
|
78
|
+
|