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,88 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* š§ Direct resolve using the fixed JackpotService (bypasses API server)
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { Connection, Keypair, Transaction } = require('@solana/web3.js');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const JackpotService = require('../services/jackpotService');
|
|
11
|
+
|
|
12
|
+
const RPC_URL = 'https://api.devnet.solana.com';
|
|
13
|
+
|
|
14
|
+
async function resolveRound() {
|
|
15
|
+
console.log('š§ Direct Round Resolution (using fixed code)\n');
|
|
16
|
+
|
|
17
|
+
// Load keeper wallet
|
|
18
|
+
const mainWalletPath = path.join(require('os').homedir(), '.config/solana/id.json');
|
|
19
|
+
const secretKey = JSON.parse(fs.readFileSync(mainWalletPath, 'utf-8'));
|
|
20
|
+
const wallet = Keypair.fromSecretKey(Uint8Array.from(secretKey));
|
|
21
|
+
|
|
22
|
+
console.log('Keeper wallet:', wallet.publicKey.toString());
|
|
23
|
+
console.log();
|
|
24
|
+
|
|
25
|
+
// Initialize service
|
|
26
|
+
const jackpotService = new JackpotService({
|
|
27
|
+
rpcUrl: RPC_URL,
|
|
28
|
+
programId: 'BHidyz25KWkNPdTHgeANzMg25MM2KEiNnG4yE5F46XUz',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Get round info
|
|
32
|
+
const round = await jackpotService.getCurrentRound();
|
|
33
|
+
console.log(`Round ${round.roundId} - Status: ${round.status}`);
|
|
34
|
+
console.log(`Pot: ${Number(round.totalPotLamports) / 1e9} SOL`);
|
|
35
|
+
console.log();
|
|
36
|
+
|
|
37
|
+
if (round.status !== 'Locked') {
|
|
38
|
+
console.log(`ā ļø Round is not locked (status: ${round.status})`);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
// Build resolve transaction using FIXED code
|
|
44
|
+
console.log('š Building resolve transaction with FIXED winner calculation...');
|
|
45
|
+
const result = await jackpotService.buildResolveRoundTransaction({
|
|
46
|
+
keeperAddress: wallet.publicKey.toString(),
|
|
47
|
+
roundId: round.roundId,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
console.log(`ā
Winner: ${result.winner}`);
|
|
51
|
+
console.log();
|
|
52
|
+
|
|
53
|
+
// Sign and send
|
|
54
|
+
console.log('āļø Signing and sending transaction...');
|
|
55
|
+
const connection = new Connection(RPC_URL, 'confirmed');
|
|
56
|
+
const tx = Transaction.from(Buffer.from(result.transaction, 'base64'));
|
|
57
|
+
tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
|
|
58
|
+
tx.feePayer = wallet.publicKey;
|
|
59
|
+
tx.sign(wallet);
|
|
60
|
+
|
|
61
|
+
const signature = await connection.sendRawTransaction(tx.serialize(), {
|
|
62
|
+
skipPreflight: false,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
console.log(`š” Transaction sent: ${signature}`);
|
|
66
|
+
console.log('ā³ Confirming...');
|
|
67
|
+
|
|
68
|
+
await connection.confirmTransaction(signature);
|
|
69
|
+
|
|
70
|
+
console.log();
|
|
71
|
+
console.log('ššš SUCCESS! Round resolved!');
|
|
72
|
+
console.log(` Winner: ${result.winner}`);
|
|
73
|
+
console.log(` Prize: ${(Number(round.totalPotLamports) * 0.95 / 1e9).toFixed(4)} SOL`);
|
|
74
|
+
console.log(` Transaction: https://explorer.solana.com/tx/${signature}?cluster=devnet`);
|
|
75
|
+
console.log();
|
|
76
|
+
console.log('ā
YOUR ROUND IS NOW UNLOCKED!');
|
|
77
|
+
console.log(' The keeper bot will reset it and start Round 51.');
|
|
78
|
+
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error('ā Error:', error.message);
|
|
81
|
+
if (error.logs) {
|
|
82
|
+
console.error('Logs:', error.logs);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
resolveRound().catch(console.error);
|
|
88
|
+
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// Manually resolve a mock game for testing
|
|
2
|
+
const { Connection, Keypair, PublicKey, Transaction, TransactionInstruction } = require('@solana/web3.js');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const crypto = require('crypto');
|
|
5
|
+
|
|
6
|
+
const PROGRAM_ID = new PublicKey('8DJTkgk6MDr6tPtw4v2VzYAz9WWvmCg6786vZrEK3o5q');
|
|
7
|
+
const OPERATOR_WALLET = new PublicKey('BVZXwZpfgyzTBdRFHohkHZppPHnAyqyctRsKy3vWfQib');
|
|
8
|
+
const RPC_URL = 'https://api.devnet.solana.com';
|
|
9
|
+
|
|
10
|
+
// Load oracle keypair
|
|
11
|
+
const oracleKeypairData = JSON.parse(fs.readFileSync('./wallets/oracle.json', 'utf-8'));
|
|
12
|
+
const oracleKeypair = Keypair.fromSecretKey(Uint8Array.from(oracleKeypairData));
|
|
13
|
+
|
|
14
|
+
console.log('š¤ Manual Game Resolution Script');
|
|
15
|
+
console.log('=================================\n');
|
|
16
|
+
console.log('Oracle wallet:', oracleKeypair.publicKey.toString());
|
|
17
|
+
console.log('Operator wallet:', OPERATOR_WALLET.toString());
|
|
18
|
+
console.log('');
|
|
19
|
+
|
|
20
|
+
const gameId = process.argv[2]; // Get from command line
|
|
21
|
+
const winner = process.argv[3]; // 'home', 'away', or 'tie'
|
|
22
|
+
|
|
23
|
+
if (!gameId || !winner) {
|
|
24
|
+
console.log('Usage: node resolve-mock-game.js <gameId> <winner>');
|
|
25
|
+
console.log('');
|
|
26
|
+
console.log('Example:');
|
|
27
|
+
console.log(' node resolve-mock-game.js sport-1761927514471-308lnavgp home');
|
|
28
|
+
console.log(' node resolve-mock-game.js sport-1761927514471-308lnavgp away');
|
|
29
|
+
console.log(' node resolve-mock-game.js sport-1761927514471-308lnavgp tie');
|
|
30
|
+
console.log('');
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function resolveGame() {
|
|
35
|
+
const connection = new Connection(RPC_URL, 'confirmed');
|
|
36
|
+
|
|
37
|
+
console.log(`Resolving game: ${gameId}`);
|
|
38
|
+
console.log(`Winner: ${winner}\n`);
|
|
39
|
+
|
|
40
|
+
// Get game PDA
|
|
41
|
+
const hash = crypto.createHash('sha256').update(gameId).digest();
|
|
42
|
+
const gameIdNum = hash.readBigUInt64LE(0);
|
|
43
|
+
const gameIdBuf = Buffer.alloc(8);
|
|
44
|
+
gameIdBuf.writeBigUInt64LE(gameIdNum);
|
|
45
|
+
|
|
46
|
+
const [gamePDA] = PublicKey.findProgramAddressSync(
|
|
47
|
+
[Buffer.from("game"), gameIdBuf],
|
|
48
|
+
PROGRAM_ID
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
console.log('Game PDA:', gamePDA.toString());
|
|
52
|
+
|
|
53
|
+
// Encode winning team
|
|
54
|
+
let winningTeamBytes;
|
|
55
|
+
if (winner === 'tie') {
|
|
56
|
+
winningTeamBytes = Buffer.from([0]); // None
|
|
57
|
+
console.log('Encoding: None (tie - refund all)');
|
|
58
|
+
} else if (winner === 'home') {
|
|
59
|
+
winningTeamBytes = Buffer.from([1, 0]); // Some(Home)
|
|
60
|
+
console.log('Encoding: Some(Home)');
|
|
61
|
+
} else if (winner === 'away') {
|
|
62
|
+
winningTeamBytes = Buffer.from([1, 1]); // Some(Away)
|
|
63
|
+
console.log('Encoding: Some(Away)');
|
|
64
|
+
} else {
|
|
65
|
+
console.log('ā Invalid winner! Use: home, away, or tie');
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Build resolve transaction
|
|
70
|
+
const RESOLVE_AUTO = Buffer.from([245, 33, 115, 150, 82, 150, 28, 193]);
|
|
71
|
+
|
|
72
|
+
const data = Buffer.concat([
|
|
73
|
+
RESOLVE_AUTO,
|
|
74
|
+
gameIdBuf,
|
|
75
|
+
winningTeamBytes
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
const ix = new TransactionInstruction({
|
|
79
|
+
keys: [
|
|
80
|
+
{ pubkey: gamePDA, isSigner: false, isWritable: true },
|
|
81
|
+
{ pubkey: oracleKeypair.publicKey, isSigner: true, isWritable: false },
|
|
82
|
+
// š Operator wallet receives fee
|
|
83
|
+
{ pubkey: OPERATOR_WALLET, isSigner: false, isWritable: true },
|
|
84
|
+
],
|
|
85
|
+
programId: PROGRAM_ID,
|
|
86
|
+
data,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
console.log('\nš¤ Submitting resolution transaction...');
|
|
90
|
+
|
|
91
|
+
const tx = new Transaction().add(ix);
|
|
92
|
+
tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
|
|
93
|
+
tx.feePayer = oracleKeypair.publicKey;
|
|
94
|
+
|
|
95
|
+
tx.sign(oracleKeypair);
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
const signature = await connection.sendRawTransaction(tx.serialize());
|
|
99
|
+
console.log('ā
Transaction sent:', signature);
|
|
100
|
+
|
|
101
|
+
console.log('\nā³ Waiting for confirmation...');
|
|
102
|
+
await connection.confirmTransaction(signature);
|
|
103
|
+
|
|
104
|
+
console.log('ā
Transaction confirmed!');
|
|
105
|
+
console.log('\nš Game resolved successfully!');
|
|
106
|
+
console.log(`\nView on explorer:`);
|
|
107
|
+
console.log(`https://explorer.solana.com/tx/${signature}?cluster=devnet`);
|
|
108
|
+
console.log('');
|
|
109
|
+
console.log('š° Check operator wallet balance:');
|
|
110
|
+
console.log(`solana balance ${OPERATOR_WALLET.toString()} --url devnet`);
|
|
111
|
+
console.log('');
|
|
112
|
+
console.log('Players can now use /claim to get their prizes!');
|
|
113
|
+
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.log('ā Error resolving game:', error.message);
|
|
116
|
+
if (error.logs) {
|
|
117
|
+
console.log('\nProgram logs:');
|
|
118
|
+
error.logs.forEach(log => console.log(' ', log));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
resolveGame().catch(console.error);
|
|
124
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-off script to resolve a pickem game via the Dubs SDK.
|
|
3
|
+
* Usage: node scripts/resolve-pickem-game.js <gameId> <winnerTeam>
|
|
4
|
+
* Example: node scripts/resolve-pickem-game.js df2f0746-b3f8-46ad-9187-e5b7d9fbca8f home
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
require('dotenv').config();
|
|
8
|
+
const { Dubs } = require('@dubsdotapp/node');
|
|
9
|
+
|
|
10
|
+
const gameId = process.argv[2];
|
|
11
|
+
const winnerTeam = process.argv[3] || 'home';
|
|
12
|
+
|
|
13
|
+
if (!gameId) {
|
|
14
|
+
console.error('Usage: node scripts/resolve-pickem-game.js <gameId> <winnerTeam>');
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const apiKey = process.env.DUBS_API_KEY;
|
|
19
|
+
const resolutionSecret = process.env.DUBS_RESOLUTION_SECRET;
|
|
20
|
+
const baseUrl = process.env.DUBS_SDK_BASE_URL;
|
|
21
|
+
|
|
22
|
+
if (!apiKey || !resolutionSecret) {
|
|
23
|
+
console.error('Missing DUBS_API_KEY or DUBS_RESOLUTION_SECRET');
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function main() {
|
|
28
|
+
const dubs = new Dubs({ apiKey, resolutionSecret, baseUrl });
|
|
29
|
+
|
|
30
|
+
console.log(`Fetching game ${gameId}...`);
|
|
31
|
+
const { game } = await dubs.games.get(gameId);
|
|
32
|
+
console.log(`Game: ${game.title}`);
|
|
33
|
+
console.log(`Status: ${game.status}, isResolved: ${game.isResolved}`);
|
|
34
|
+
console.log(`Bettors: ${game.bettors?.length ?? 0}`);
|
|
35
|
+
for (const b of game.bettors || []) {
|
|
36
|
+
console.log(` ${b.wallet} ā team: ${b.team}, amount: ${b.amount}`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (game.isResolved) {
|
|
40
|
+
console.log('Game already resolved. Nothing to do.');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log(`\nResolving with winner: '${winnerTeam}'...`);
|
|
45
|
+
const result = await dubs.resolveGame(gameId, {
|
|
46
|
+
winner: winnerTeam,
|
|
47
|
+
metadata: { source: 'manual_pickem_resolve' },
|
|
48
|
+
});
|
|
49
|
+
console.log('Resolved!', JSON.stringify(result, null, 2));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
main().catch(err => {
|
|
53
|
+
console.error('Error:', err.message);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { Connection, Keypair, PublicKey, Transaction, TransactionInstruction } = require('@solana/web3.js');
|
|
4
|
+
const crypto = require('crypto');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
8
|
+
const PROGRAM_ID = new PublicKey('BHidyz25KWkNPdTHgeANzMg25MM2KEiNnG4yE5F46XUz');
|
|
9
|
+
const RPC_URL = 'https://api.devnet.solana.com';
|
|
10
|
+
|
|
11
|
+
async function main() {
|
|
12
|
+
const connection = new Connection(RPC_URL, 'confirmed');
|
|
13
|
+
|
|
14
|
+
// Load oracle wallet
|
|
15
|
+
const oracleKeyPath = path.join(__dirname, '..', 'wallets', 'jackpot_oracle.json');
|
|
16
|
+
const secretKey = JSON.parse(fs.readFileSync(oracleKeyPath, 'utf-8'));
|
|
17
|
+
const oracle = Keypair.fromSecretKey(Uint8Array.from(secretKey));
|
|
18
|
+
|
|
19
|
+
console.log('š² Manual Round Resolution');
|
|
20
|
+
console.log('Oracle:', oracle.publicKey.toString());
|
|
21
|
+
|
|
22
|
+
// Get config
|
|
23
|
+
const [configPda] = PublicKey.findProgramAddressSync([Buffer.from('config')], PROGRAM_ID);
|
|
24
|
+
const configData = await connection.getAccountInfo(configPda);
|
|
25
|
+
const currentRoundId = configData.data.readBigUInt64LE(82);
|
|
26
|
+
|
|
27
|
+
console.log('Current Round ID:', currentRoundId.toString());
|
|
28
|
+
|
|
29
|
+
// Get round PDA
|
|
30
|
+
const roundIdBuf = Buffer.alloc(8);
|
|
31
|
+
roundIdBuf.writeBigUInt64LE(currentRoundId);
|
|
32
|
+
const [roundPda] = PublicKey.findProgramAddressSync([Buffer.from('round'), roundIdBuf], PROGRAM_ID);
|
|
33
|
+
|
|
34
|
+
console.log('Round PDA:', roundPda.toString());
|
|
35
|
+
|
|
36
|
+
// Check round status
|
|
37
|
+
const roundData = await connection.getAccountInfo(roundPda);
|
|
38
|
+
if (!roundData) {
|
|
39
|
+
console.log('ā Round account not found');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const status = roundData.data[16]; // 0=Open, 1=Locked, 2=Resolved
|
|
44
|
+
console.log('Status:', ['Open', 'Locked', 'Resolved'][status]);
|
|
45
|
+
|
|
46
|
+
if (status !== 1) {
|
|
47
|
+
console.log('ā Round is not locked');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Submit oracle randomness
|
|
52
|
+
console.log('\nš² Submitting oracle randomness...');
|
|
53
|
+
const oracleSeed = crypto.randomBytes(32);
|
|
54
|
+
|
|
55
|
+
const CONSUME_RANDOMNESS_DISC = Buffer.from([190, 217, 49, 162, 99, 26, 73, 234]);
|
|
56
|
+
const data = Buffer.concat([CONSUME_RANDOMNESS_DISC, oracleSeed]);
|
|
57
|
+
|
|
58
|
+
const keys = [
|
|
59
|
+
{ pubkey: configPda, isSigner: false, isWritable: true },
|
|
60
|
+
{ pubkey: roundPda, isSigner: false, isWritable: true },
|
|
61
|
+
{ pubkey: oracle.publicKey, isSigner: true, isWritable: false },
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
const instruction = new TransactionInstruction({ keys, programId: PROGRAM_ID, data });
|
|
65
|
+
const tx = new Transaction().add(instruction);
|
|
66
|
+
tx.feePayer = oracle.publicKey;
|
|
67
|
+
tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
|
|
68
|
+
tx.sign(oracle);
|
|
69
|
+
|
|
70
|
+
const sig = await connection.sendRawTransaction(tx.serialize(), { skipPreflight: true });
|
|
71
|
+
await connection.confirmTransaction(sig);
|
|
72
|
+
|
|
73
|
+
console.log('ā
Randomness submitted! Sig:', sig.slice(0, 8) + '...');
|
|
74
|
+
console.log('\nš” Now run: node scripts/open-jackpot-round.js to resolve and open next round');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
main().catch(console.error);
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|