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,382 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Manual Game Resolution Script
|
|
4
|
+
* Resolves stuck sports games when the oracle fails
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* node resolve-stuck-game.js --game-id <game_id> --winner <home|away|tie>
|
|
8
|
+
*
|
|
9
|
+
* Example:
|
|
10
|
+
* node resolve-stuck-game.js --game-id sport-1766418200917-00ram5nn3 --winner home
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
require('dotenv').config();
|
|
14
|
+
const {
|
|
15
|
+
Connection,
|
|
16
|
+
PublicKey,
|
|
17
|
+
Keypair,
|
|
18
|
+
Transaction,
|
|
19
|
+
TransactionInstruction,
|
|
20
|
+
} = require('@solana/web3.js');
|
|
21
|
+
const crypto = require('crypto');
|
|
22
|
+
const fs = require('fs');
|
|
23
|
+
const path = require('path');
|
|
24
|
+
|
|
25
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
26
|
+
// CONFIGURATION
|
|
27
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
28
|
+
|
|
29
|
+
// Program ID (mainnet - use env var or default)
|
|
30
|
+
const PROGRAM_ID = new PublicKey(process.env.PROGRAM_ID || '85wJGp9uc8w2FeKX9CEHsudTo1UVCrmuRFy37oCcaoG1');
|
|
31
|
+
|
|
32
|
+
// Hardcoded operator wallet (from program)
|
|
33
|
+
const OPERATOR_WALLET = new PublicKey('BVZXwZpfgyzTBdRFHohkHZppPHnAyqyctRsKy3vWfQib');
|
|
34
|
+
|
|
35
|
+
// Instruction discriminator for resolve_automatic_game
|
|
36
|
+
const RESOLVE_AUTO_DISCRIMINATOR = Buffer.from([245, 33, 115, 150, 82, 150, 28, 193]);
|
|
37
|
+
|
|
38
|
+
// RPC endpoint
|
|
39
|
+
const RPC_URL = process.env.SOLANA_RPC_URL || process.env.SOLANA_NETWORK || 'https://api.mainnet-beta.solana.com';
|
|
40
|
+
|
|
41
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
42
|
+
|
|
43
|
+
console.log('🔧 Manual Game Resolution Tool');
|
|
44
|
+
console.log('================================');
|
|
45
|
+
console.log(`RPC: ${RPC_URL}`);
|
|
46
|
+
console.log(`Program: ${PROGRAM_ID.toString()}`);
|
|
47
|
+
console.log('');
|
|
48
|
+
|
|
49
|
+
const connection = new Connection(RPC_URL, 'confirmed');
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Load oracle wallet from environment or file
|
|
53
|
+
*/
|
|
54
|
+
function loadOracleWallet() {
|
|
55
|
+
// Try environment variable first (ORACLE_WALLET_JSON for Heroku)
|
|
56
|
+
if (process.env.ORACLE_WALLET_JSON) {
|
|
57
|
+
console.log('🔑 Loading oracle wallet from ORACLE_WALLET_JSON env var');
|
|
58
|
+
const secretKey = JSON.parse(process.env.ORACLE_WALLET_JSON);
|
|
59
|
+
return Keypair.fromSecretKey(Uint8Array.from(secretKey));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Try file path
|
|
63
|
+
const walletPaths = [
|
|
64
|
+
process.env.ORACLE_WALLET_PATH,
|
|
65
|
+
path.join(__dirname, '../wallets/oracle.json'),
|
|
66
|
+
path.join(__dirname, 'wallets/oracle.json'),
|
|
67
|
+
].filter(Boolean);
|
|
68
|
+
|
|
69
|
+
for (const walletPath of walletPaths) {
|
|
70
|
+
if (fs.existsSync(walletPath)) {
|
|
71
|
+
console.log('🔑 Loading oracle wallet from:', walletPath);
|
|
72
|
+
const secretKey = JSON.parse(fs.readFileSync(walletPath, 'utf-8'));
|
|
73
|
+
return Keypair.fromSecretKey(Uint8Array.from(secretKey));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.error('❌ Oracle wallet not found!');
|
|
78
|
+
console.log(' Set ORACLE_WALLET_JSON env var or create wallets/oracle.json');
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Convert string game ID to u64 using SHA256 hash (same as oracle)
|
|
84
|
+
*/
|
|
85
|
+
function gameIdToU64(gameId) {
|
|
86
|
+
if (typeof gameId === 'string' && gameId.includes('-')) {
|
|
87
|
+
const hash = crypto.createHash('sha256').update(gameId).digest();
|
|
88
|
+
return hash.readBigUInt64LE(0);
|
|
89
|
+
}
|
|
90
|
+
return BigInt(gameId);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get game PDA from game ID
|
|
95
|
+
*/
|
|
96
|
+
function getGamePDA(gameId) {
|
|
97
|
+
const gameIdNum = gameIdToU64(gameId);
|
|
98
|
+
const gameIdBuf = Buffer.alloc(8);
|
|
99
|
+
gameIdBuf.writeBigUInt64LE(gameIdNum);
|
|
100
|
+
|
|
101
|
+
const [gamePDA] = PublicKey.findProgramAddressSync(
|
|
102
|
+
[Buffer.from("game"), gameIdBuf],
|
|
103
|
+
PROGRAM_ID
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
return { gamePDA, gameIdNum, gameIdBuf };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Build resolve_automatic_game instruction
|
|
111
|
+
*/
|
|
112
|
+
function buildResolveInstruction(gamePDA, gameIdBuf, winner, oracleWallet) {
|
|
113
|
+
// Encode winning team: Some(Home) = [1, 0], Some(Away) = [1, 1], None (tie/refund) = [0]
|
|
114
|
+
let winningTeamBytes;
|
|
115
|
+
if (winner === 'tie' || winner === 'refund') {
|
|
116
|
+
winningTeamBytes = Buffer.from([0]); // None - refund all
|
|
117
|
+
} else if (winner === 'home') {
|
|
118
|
+
winningTeamBytes = Buffer.from([1, 0]); // Some(Home)
|
|
119
|
+
} else if (winner === 'away') {
|
|
120
|
+
winningTeamBytes = Buffer.from([1, 1]); // Some(Away)
|
|
121
|
+
} else {
|
|
122
|
+
throw new Error(`Invalid winner: ${winner}. Must be 'home', 'away', or 'tie'`);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const data = Buffer.concat([
|
|
126
|
+
RESOLVE_AUTO_DISCRIMINATOR,
|
|
127
|
+
gameIdBuf,
|
|
128
|
+
winningTeamBytes,
|
|
129
|
+
]);
|
|
130
|
+
|
|
131
|
+
return new TransactionInstruction({
|
|
132
|
+
keys: [
|
|
133
|
+
{ pubkey: gamePDA, isSigner: false, isWritable: true },
|
|
134
|
+
{ pubkey: oracleWallet.publicKey, isSigner: true, isWritable: true }, // Receives 2% oracle fee
|
|
135
|
+
{ pubkey: OPERATOR_WALLET, isSigner: false, isWritable: true }, // Receives 10% operator fee
|
|
136
|
+
],
|
|
137
|
+
programId: PROGRAM_ID,
|
|
138
|
+
data,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Poll for transaction confirmation
|
|
144
|
+
*/
|
|
145
|
+
async function confirmTransaction(signature, timeout = 60000) {
|
|
146
|
+
const start = Date.now();
|
|
147
|
+
|
|
148
|
+
while (Date.now() - start < timeout) {
|
|
149
|
+
const statuses = await connection.getSignatureStatuses([signature]);
|
|
150
|
+
const status = statuses?.value?.[0];
|
|
151
|
+
|
|
152
|
+
if (status?.err) {
|
|
153
|
+
throw new Error(`Transaction failed: ${JSON.stringify(status.err)}`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (status?.confirmationStatus === 'confirmed' || status?.confirmationStatus === 'finalized') {
|
|
157
|
+
return status;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
throw new Error('Transaction confirmation timeout');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Resolve a game
|
|
168
|
+
*/
|
|
169
|
+
async function resolveGame(gameId, winner, oracleWallet) {
|
|
170
|
+
console.log(`\n📍 Resolving game: ${gameId}`);
|
|
171
|
+
console.log(` Winner: ${winner.toUpperCase()}`);
|
|
172
|
+
|
|
173
|
+
const { gamePDA, gameIdNum, gameIdBuf } = getGamePDA(gameId);
|
|
174
|
+
console.log(` Game PDA: ${gamePDA.toString()}`);
|
|
175
|
+
console.log(` Game ID (u64): ${gameIdNum.toString()}`);
|
|
176
|
+
|
|
177
|
+
// Check if game account exists
|
|
178
|
+
const accountInfo = await connection.getAccountInfo(gamePDA);
|
|
179
|
+
if (!accountInfo) {
|
|
180
|
+
console.error(' ❌ Game account not found on-chain!');
|
|
181
|
+
console.log(' This could mean:');
|
|
182
|
+
console.log(' 1. The game was never created on-chain (only in database)');
|
|
183
|
+
console.log(' 2. The game ID is incorrect');
|
|
184
|
+
console.log(' 3. The program ID is wrong');
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
console.log(` ✅ Game account found (${accountInfo.data.length} bytes)`);
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
const ix = buildResolveInstruction(gamePDA, gameIdBuf, winner, oracleWallet);
|
|
191
|
+
const tx = new Transaction().add(ix);
|
|
192
|
+
|
|
193
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
194
|
+
tx.recentBlockhash = blockhash;
|
|
195
|
+
tx.feePayer = oracleWallet.publicKey;
|
|
196
|
+
|
|
197
|
+
// Sign the transaction
|
|
198
|
+
tx.sign(oracleWallet);
|
|
199
|
+
|
|
200
|
+
console.log(' 📡 Sending resolve transaction...');
|
|
201
|
+
const signature = await connection.sendRawTransaction(tx.serialize(), {
|
|
202
|
+
skipPreflight: false,
|
|
203
|
+
preflightCommitment: 'confirmed',
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
console.log(` 📝 Signature: ${signature}`);
|
|
207
|
+
console.log(` 🔗 https://solscan.io/tx/${signature}`);
|
|
208
|
+
console.log(' ⏳ Confirming...');
|
|
209
|
+
|
|
210
|
+
await confirmTransaction(signature);
|
|
211
|
+
|
|
212
|
+
console.log(` ✅ Game resolved successfully!`);
|
|
213
|
+
return signature;
|
|
214
|
+
|
|
215
|
+
} catch (error) {
|
|
216
|
+
if (error.logs) {
|
|
217
|
+
console.error(' 📋 Program Logs:');
|
|
218
|
+
error.logs.forEach(log => console.error(` ${log}`));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (error.message?.includes('AlreadyResolved') || error.message?.includes('0x1796')) {
|
|
222
|
+
console.log(' ℹ️ Game is already resolved');
|
|
223
|
+
return 'already_resolved';
|
|
224
|
+
}
|
|
225
|
+
if (error.message?.includes('CannotResolveBeforeLockTime') || error.message?.includes('0x179b')) {
|
|
226
|
+
console.log(' ⏰ Cannot resolve - lock time hasn\'t passed yet');
|
|
227
|
+
return 'too_early';
|
|
228
|
+
}
|
|
229
|
+
if (error.message?.includes('InvalidOracle') || error.message?.includes('0x1799')) {
|
|
230
|
+
console.log(' 🔐 Invalid oracle - your wallet is not the authorized oracle for this game');
|
|
231
|
+
return 'invalid_oracle';
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
console.error(` ❌ Error: ${error.message}`);
|
|
235
|
+
throw error;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Update database after resolution
|
|
241
|
+
*/
|
|
242
|
+
async function updateDatabase(gameId, winner, homeScore, awayScore) {
|
|
243
|
+
const axios = require('axios');
|
|
244
|
+
const dubsServerUrl = process.env.DUBS_SERVER_URL || 'http://localhost:3001';
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
console.log(`\n📡 Updating database at ${dubsServerUrl}...`);
|
|
248
|
+
|
|
249
|
+
await axios.post(
|
|
250
|
+
`${dubsServerUrl}/api/games/${gameId}/resolve`,
|
|
251
|
+
{
|
|
252
|
+
winner,
|
|
253
|
+
homeScore,
|
|
254
|
+
awayScore,
|
|
255
|
+
resolvedAt: new Date().toISOString(),
|
|
256
|
+
resolvedBy: 'manual_script'
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
timeout: 10000,
|
|
260
|
+
headers: { 'Content-Type': 'application/json' }
|
|
261
|
+
}
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
console.log(' ✅ Database updated');
|
|
265
|
+
} catch (error) {
|
|
266
|
+
console.error(' ⚠️ Failed to update database:', error.message);
|
|
267
|
+
console.log(' You may need to update it manually');
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Main execution
|
|
273
|
+
*/
|
|
274
|
+
async function main() {
|
|
275
|
+
const args = process.argv.slice(2);
|
|
276
|
+
|
|
277
|
+
// Parse arguments
|
|
278
|
+
let gameId = null;
|
|
279
|
+
let winner = null;
|
|
280
|
+
let homeScore = null;
|
|
281
|
+
let awayScore = null;
|
|
282
|
+
let skipDb = false;
|
|
283
|
+
|
|
284
|
+
for (let i = 0; i < args.length; i++) {
|
|
285
|
+
if (args[i] === '--game-id' && args[i + 1]) {
|
|
286
|
+
gameId = args[i + 1];
|
|
287
|
+
i++;
|
|
288
|
+
} else if (args[i] === '--winner' && args[i + 1]) {
|
|
289
|
+
winner = args[i + 1].toLowerCase();
|
|
290
|
+
i++;
|
|
291
|
+
} else if (args[i] === '--home-score' && args[i + 1]) {
|
|
292
|
+
homeScore = parseInt(args[i + 1]);
|
|
293
|
+
i++;
|
|
294
|
+
} else if (args[i] === '--away-score' && args[i + 1]) {
|
|
295
|
+
awayScore = parseInt(args[i + 1]);
|
|
296
|
+
i++;
|
|
297
|
+
} else if (args[i] === '--skip-db') {
|
|
298
|
+
skipDb = true;
|
|
299
|
+
} else if (args[i] === '--help' || args[i] === '-h') {
|
|
300
|
+
console.log('Usage:');
|
|
301
|
+
console.log(' node resolve-stuck-game.js --game-id <id> --winner <home|away|tie> [options]');
|
|
302
|
+
console.log('');
|
|
303
|
+
console.log('Options:');
|
|
304
|
+
console.log(' --game-id <id> The game ID from the database (e.g., sport-1766418200917-00ram5nn3)');
|
|
305
|
+
console.log(' --winner <choice> Winner: home, away, or tie (tie = refund all)');
|
|
306
|
+
console.log(' --home-score <n> Final home team score (for database update)');
|
|
307
|
+
console.log(' --away-score <n> Final away team score (for database update)');
|
|
308
|
+
console.log(' --skip-db Skip database update (only resolve on-chain)');
|
|
309
|
+
console.log('');
|
|
310
|
+
console.log('Environment variables:');
|
|
311
|
+
console.log(' ORACLE_WALLET_JSON Oracle private key as JSON array');
|
|
312
|
+
console.log(' ORACLE_WALLET_PATH Path to oracle wallet JSON file');
|
|
313
|
+
console.log(' SOLANA_RPC_URL Solana RPC endpoint');
|
|
314
|
+
console.log(' PROGRAM_ID Solana program ID');
|
|
315
|
+
console.log(' DUBS_SERVER_URL Server URL for database updates');
|
|
316
|
+
console.log('');
|
|
317
|
+
console.log('Example:');
|
|
318
|
+
console.log(' node resolve-stuck-game.js --game-id sport-1766418200917-00ram5nn3 --winner home --home-score 23 --away-score 10');
|
|
319
|
+
process.exit(0);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Validate required arguments
|
|
324
|
+
if (!gameId) {
|
|
325
|
+
console.error('❌ Missing --game-id argument');
|
|
326
|
+
console.log(' Run with --help for usage');
|
|
327
|
+
process.exit(1);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (!winner) {
|
|
331
|
+
console.error('❌ Missing --winner argument');
|
|
332
|
+
console.log(' Run with --help for usage');
|
|
333
|
+
process.exit(1);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (!['home', 'away', 'tie', 'refund'].includes(winner)) {
|
|
337
|
+
console.error(`❌ Invalid winner: ${winner}`);
|
|
338
|
+
console.log(' Must be: home, away, or tie');
|
|
339
|
+
process.exit(1);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
console.log('📋 Resolution Details:');
|
|
343
|
+
console.log(` Game ID: ${gameId}`);
|
|
344
|
+
console.log(` Winner: ${winner.toUpperCase()}`);
|
|
345
|
+
if (homeScore !== null) console.log(` Home Score: ${homeScore}`);
|
|
346
|
+
if (awayScore !== null) console.log(` Away Score: ${awayScore}`);
|
|
347
|
+
console.log('');
|
|
348
|
+
|
|
349
|
+
// Load oracle wallet
|
|
350
|
+
console.log('🔐 Loading oracle wallet...');
|
|
351
|
+
const oracleWallet = loadOracleWallet();
|
|
352
|
+
console.log(` Oracle: ${oracleWallet.publicKey.toString()}`);
|
|
353
|
+
|
|
354
|
+
// Check oracle balance
|
|
355
|
+
const balance = await connection.getBalance(oracleWallet.publicKey);
|
|
356
|
+
console.log(` Balance: ${balance / 1e9} SOL`);
|
|
357
|
+
|
|
358
|
+
if (balance < 10000000) { // 0.01 SOL
|
|
359
|
+
console.error(' ⚠️ Low balance! May not have enough for transaction fees');
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Resolve on-chain
|
|
363
|
+
const result = await resolveGame(gameId, winner, oracleWallet);
|
|
364
|
+
|
|
365
|
+
if (result && result !== 'already_resolved' && result !== 'too_early' && result !== 'invalid_oracle') {
|
|
366
|
+
// Update database if not skipped
|
|
367
|
+
if (!skipDb && homeScore !== null && awayScore !== null) {
|
|
368
|
+
await updateDatabase(gameId, winner, homeScore, awayScore);
|
|
369
|
+
} else if (!skipDb) {
|
|
370
|
+
console.log('\n💡 Tip: Add --home-score and --away-score to also update the database');
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
console.log('\n✅ Done!');
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
main().catch(error => {
|
|
378
|
+
console.error('\n❌ Fatal error:', error.message);
|
|
379
|
+
process.exit(1);
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { Connection, Keypair, Transaction, PublicKey } = require('@solana/web3.js');
|
|
4
|
+
const axios = require('axios');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
8
|
+
const RPC_URL = 'https://api.devnet.solana.com';
|
|
9
|
+
const API_BASE = 'http://localhost:3001';
|
|
10
|
+
|
|
11
|
+
async function main() {
|
|
12
|
+
const oracleKeyPath = path.join(__dirname, '..', 'wallets', 'jackpot_oracle.json');
|
|
13
|
+
const secretKey = JSON.parse(fs.readFileSync(oracleKeyPath, 'utf-8'));
|
|
14
|
+
const wallet = Keypair.fromSecretKey(Uint8Array.from(secretKey));
|
|
15
|
+
|
|
16
|
+
console.log('🔧 Resolving stuck round...');
|
|
17
|
+
console.log('Wallet:', wallet.publicKey.toString());
|
|
18
|
+
|
|
19
|
+
const connection = new Connection(RPC_URL, 'confirmed');
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
const { data } = await axios.post(`${API_BASE}/jackpot/build/resolve`, {
|
|
23
|
+
keeperAddress: wallet.publicKey.toString(),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const tx = Transaction.from(Buffer.from(data.transaction, 'base64'));
|
|
27
|
+
tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
|
|
28
|
+
tx.feePayer = wallet.publicKey;
|
|
29
|
+
tx.sign(wallet);
|
|
30
|
+
|
|
31
|
+
const signature = await connection.sendRawTransaction(tx.serialize(), { skipPreflight: false });
|
|
32
|
+
console.log('Signature:', signature);
|
|
33
|
+
|
|
34
|
+
await connection.confirmTransaction(signature);
|
|
35
|
+
console.log('✅ Round resolved!');
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.error('❌ Error:', error.response?.data || error.message);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
main();
|
|
42
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Run Connect4 columns migration
|
|
3
|
+
# This adds missing columns to the games table for Connect4 support
|
|
4
|
+
|
|
5
|
+
echo "Running Connect4 columns migration..."
|
|
6
|
+
|
|
7
|
+
# Check if DATABASE_URL is set
|
|
8
|
+
if [ -z "$DATABASE_URL" ]; then
|
|
9
|
+
echo "DATABASE_URL not set, using local dubs_db"
|
|
10
|
+
psql -d dubs_db -f scripts/migrations/008_add_connect4_columns.sql
|
|
11
|
+
else
|
|
12
|
+
echo "Using DATABASE_URL"
|
|
13
|
+
psql "$DATABASE_URL" -f scripts/migrations/008_add_connect4_columns.sql
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
echo "Done!"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Run the mention system migration
|
|
4
|
+
# Usage: ./scripts/run-mention-migration.sh
|
|
5
|
+
|
|
6
|
+
echo "🔄 Running mention system migration..."
|
|
7
|
+
|
|
8
|
+
# Check if DATABASE_URL is set
|
|
9
|
+
if [ -z "$DATABASE_URL" ]; then
|
|
10
|
+
echo "❌ ERROR: DATABASE_URL environment variable is not set"
|
|
11
|
+
echo "Please set it with: export DATABASE_URL=your_database_url"
|
|
12
|
+
exit 1
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
# Run the migration
|
|
16
|
+
psql "$DATABASE_URL" -f scripts/add_mention_system.sql
|
|
17
|
+
|
|
18
|
+
if [ $? -eq 0 ]; then
|
|
19
|
+
echo "✅ Mention system migration completed successfully!"
|
|
20
|
+
else
|
|
21
|
+
echo "❌ Migration failed. Please check the error messages above."
|
|
22
|
+
exit 1
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# ========================================
|
|
4
|
+
# Payment System Migration Runner
|
|
5
|
+
# ========================================
|
|
6
|
+
# Runs the payment system database migration
|
|
7
|
+
# Usage: ./scripts/run-payment-migration.sh
|
|
8
|
+
|
|
9
|
+
set -e
|
|
10
|
+
|
|
11
|
+
echo "🚀 Running Payment System Migration..."
|
|
12
|
+
echo ""
|
|
13
|
+
|
|
14
|
+
# Check if DATABASE_URL is set
|
|
15
|
+
if [ -z "$DATABASE_URL" ]; then
|
|
16
|
+
echo "❌ ERROR: DATABASE_URL environment variable is not set"
|
|
17
|
+
echo ""
|
|
18
|
+
echo "Please set it first:"
|
|
19
|
+
echo " export DATABASE_URL='postgresql://user:pass@host:port/dbname'"
|
|
20
|
+
exit 1
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
echo "📊 Database: ${DATABASE_URL%%@*}@***"
|
|
24
|
+
echo ""
|
|
25
|
+
|
|
26
|
+
# Run the migration
|
|
27
|
+
echo "📝 Executing migration SQL..."
|
|
28
|
+
psql "$DATABASE_URL" -f scripts/add_payment_system.sql
|
|
29
|
+
|
|
30
|
+
echo ""
|
|
31
|
+
echo "✅ Payment system migration completed successfully!"
|
|
32
|
+
echo ""
|
|
33
|
+
echo "New features enabled:"
|
|
34
|
+
echo " • chat_payments table created"
|
|
35
|
+
echo " • Payment notification types added"
|
|
36
|
+
echo " • Indexes created for performance"
|
|
37
|
+
echo ""
|
|
38
|
+
echo "You can now:"
|
|
39
|
+
echo " 1. Send SOL payments via @mention $amount"
|
|
40
|
+
echo " 2. Track payment history"
|
|
41
|
+
echo " 3. Receive payment notifications"
|
|
42
|
+
echo ""
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Run preferred_currency migration
|
|
3
|
+
|
|
4
|
+
# Get DATABASE_URL from environment or .env file
|
|
5
|
+
if [ -f .env ]; then
|
|
6
|
+
export $(cat .env | grep DATABASE_URL | xargs)
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
echo "🔄 Running preferred_currency migration..."
|
|
10
|
+
echo "Database: $DATABASE_URL"
|
|
11
|
+
|
|
12
|
+
psql "$DATABASE_URL" -f scripts/add-preferred-currency.sql
|
|
13
|
+
|
|
14
|
+
if [ $? -eq 0 ]; then
|
|
15
|
+
echo "✅ Migration completed successfully!"
|
|
16
|
+
echo ""
|
|
17
|
+
echo "To verify, run:"
|
|
18
|
+
echo " psql \$DATABASE_URL -c \"\\d users\" | grep preferred"
|
|
19
|
+
else
|
|
20
|
+
echo "❌ Migration failed!"
|
|
21
|
+
exit 1
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Run the referral earnings migration
|
|
4
|
+
# Usage: ./scripts/run-referral-earnings-migration.sh
|
|
5
|
+
|
|
6
|
+
echo "💰 Running Referral Earnings Migration..."
|
|
7
|
+
echo ""
|
|
8
|
+
|
|
9
|
+
# Check if DATABASE_URL is set
|
|
10
|
+
if [ -z "$DATABASE_URL" ]; then
|
|
11
|
+
echo "❌ DATABASE_URL environment variable is not set"
|
|
12
|
+
echo " Please set it before running this script:"
|
|
13
|
+
echo " export DATABASE_URL=postgres://user:pass@host:5432/dbname"
|
|
14
|
+
exit 1
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
# Run the migration
|
|
18
|
+
psql "$DATABASE_URL" -f scripts/migrations/003_referral_earnings.sql
|
|
19
|
+
|
|
20
|
+
if [ $? -eq 0 ]; then
|
|
21
|
+
echo ""
|
|
22
|
+
echo "✅ Migration completed successfully!"
|
|
23
|
+
echo ""
|
|
24
|
+
echo "📊 Verifying tables were created..."
|
|
25
|
+
psql "$DATABASE_URL" -c "SELECT table_name FROM information_schema.tables WHERE table_name LIKE 'referral%' ORDER BY table_name;"
|
|
26
|
+
else
|
|
27
|
+
echo ""
|
|
28
|
+
echo "❌ Migration failed. Check the errors above."
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Run Survivor Pool outcome migration
|
|
3
|
+
# This adds winner_type and completed_at columns for tracking pool outcomes
|
|
4
|
+
|
|
5
|
+
echo "Running Survivor Pool outcome migration..."
|
|
6
|
+
|
|
7
|
+
# Check if DATABASE_URL is set
|
|
8
|
+
if [ -z "$DATABASE_URL" ]; then
|
|
9
|
+
echo "DATABASE_URL not set, using local dubs_db"
|
|
10
|
+
psql -d dubs_db -f scripts/migrations/010_add_survivor_pool_outcome.sql
|
|
11
|
+
else
|
|
12
|
+
echo "Using DATABASE_URL"
|
|
13
|
+
psql "$DATABASE_URL" -f scripts/migrations/010_add_survivor_pool_outcome.sql
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
echo "Done!"
|