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,370 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Test Script: Connect4 Cancel and Claim Flow
|
|
4
|
+
*
|
|
5
|
+
* Tests the full flow of:
|
|
6
|
+
* 1. Creating a Connect4 game
|
|
7
|
+
* 2. Cancelling the game
|
|
8
|
+
* 3. Claiming the refund
|
|
9
|
+
*
|
|
10
|
+
* This validates the fix for the Alchemy WebSocket issue.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* node test-connect4-cancel-claim.js # Run full test with new game
|
|
14
|
+
* node test-connect4-cancel-claim.js --game-id=<id> # Test claim on existing cancelled game
|
|
15
|
+
* node test-connect4-cancel-claim.js --cancel-only=<id> # Just cancel an existing game
|
|
16
|
+
* node test-connect4-cancel-claim.js --claim-only=<id> # Just claim an existing cancelled game
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
require('dotenv').config();
|
|
20
|
+
const { Connection, Keypair, PublicKey } = require('@solana/web3.js');
|
|
21
|
+
const { pool } = require('../services/db');
|
|
22
|
+
const axios = require('axios');
|
|
23
|
+
|
|
24
|
+
// Configuration
|
|
25
|
+
const RPC_URL = process.env.SOLANA_RPC_URL || process.env.SOLANA_NETWORK || 'https://api.devnet.solana.com';
|
|
26
|
+
const SERVER_URL = process.env.TEST_SERVER_URL || 'http://localhost:3001';
|
|
27
|
+
const PROGRAM_ID = new PublicKey(process.env.PROGRAM_ID || '85wJGp9uc8w2FeKX9CEHsudTo1UVCrmuRFy37oCcaoG1');
|
|
28
|
+
|
|
29
|
+
// Parse args
|
|
30
|
+
const args = process.argv.slice(2);
|
|
31
|
+
const options = {};
|
|
32
|
+
args.forEach(arg => {
|
|
33
|
+
if (arg.startsWith('--game-id=')) options.gameId = arg.split('=')[1];
|
|
34
|
+
if (arg.startsWith('--cancel-only=')) options.cancelOnly = arg.split('=')[1];
|
|
35
|
+
if (arg.startsWith('--claim-only=')) options.claimOnly = arg.split('=')[1];
|
|
36
|
+
if (arg === '--help') options.help = true;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
console.log('🧪 Connect4 Cancel & Claim Flow Test');
|
|
40
|
+
console.log('=====================================');
|
|
41
|
+
console.log(`RPC URL: ${RPC_URL}`);
|
|
42
|
+
console.log(`Server URL: ${SERVER_URL}`);
|
|
43
|
+
console.log(`Program ID: ${PROGRAM_ID.toString()}`);
|
|
44
|
+
console.log('');
|
|
45
|
+
|
|
46
|
+
const connection = new Connection(RPC_URL, 'confirmed');
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get a test auth token for API calls
|
|
50
|
+
*/
|
|
51
|
+
async function getTestAuthToken(walletAddress) {
|
|
52
|
+
// In a real test, you'd authenticate properly
|
|
53
|
+
// For now, we'll query the database directly for an existing user
|
|
54
|
+
const result = await pool.query(
|
|
55
|
+
'SELECT dubs_auth_token FROM users WHERE wallet_address = $1 LIMIT 1',
|
|
56
|
+
[walletAddress]
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
if (result.rows.length > 0 && result.rows[0].dubs_auth_token) {
|
|
60
|
+
return result.rows[0].dubs_auth_token;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
throw new Error(`No auth token found for wallet ${walletAddress}. User must be registered first.`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Find a cancelled Connect4 game that hasn't been claimed
|
|
68
|
+
*/
|
|
69
|
+
async function findCancelledUnclaimedGame() {
|
|
70
|
+
console.log('🔍 Looking for cancelled unclaimed Connect4 games...');
|
|
71
|
+
|
|
72
|
+
const result = await pool.query(`
|
|
73
|
+
SELECT g.game_id, g.buy_in, g.is_resolved, g.connect4_winner as winner, g.game_status,
|
|
74
|
+
creator.wallet_address as creator_wallet, creator.claimed_at
|
|
75
|
+
FROM games g
|
|
76
|
+
LEFT JOIN user_game_refs creator ON g.game_id = creator.game_id AND creator.role = 'creator'
|
|
77
|
+
WHERE g.game_type = 'connect4'
|
|
78
|
+
AND g.game_status = 'cancelled'
|
|
79
|
+
AND g.is_resolved = TRUE
|
|
80
|
+
AND creator.claimed_at IS NULL
|
|
81
|
+
ORDER BY g.created_at DESC
|
|
82
|
+
LIMIT 5
|
|
83
|
+
`);
|
|
84
|
+
|
|
85
|
+
if (result.rows.length === 0) {
|
|
86
|
+
console.log(' No cancelled unclaimed games found');
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.log(` Found ${result.rows.length} cancelled unclaimed game(s):`);
|
|
91
|
+
result.rows.forEach(g => {
|
|
92
|
+
console.log(` - ${g.game_id} (creator: ${g.creator_wallet?.slice(0, 8)}..., buy_in: ${g.buy_in})`);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return result.rows[0];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Find an active Connect4 game that can be cancelled
|
|
100
|
+
*/
|
|
101
|
+
async function findActiveCancellableGame() {
|
|
102
|
+
console.log('🔍 Looking for active Connect4 games that can be cancelled...');
|
|
103
|
+
|
|
104
|
+
const result = await pool.query(`
|
|
105
|
+
SELECT g.game_id, g.buy_in, g.game_status,
|
|
106
|
+
creator.wallet_address as creator_wallet
|
|
107
|
+
FROM games g
|
|
108
|
+
LEFT JOIN user_game_refs creator ON g.game_id = creator.game_id AND creator.role = 'creator'
|
|
109
|
+
WHERE g.game_type = 'connect4'
|
|
110
|
+
AND g.game_status IN ('waiting', 'pending')
|
|
111
|
+
AND g.is_resolved = FALSE
|
|
112
|
+
ORDER BY g.created_at DESC
|
|
113
|
+
LIMIT 5
|
|
114
|
+
`);
|
|
115
|
+
|
|
116
|
+
if (result.rows.length === 0) {
|
|
117
|
+
console.log(' No cancellable games found');
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
console.log(` Found ${result.rows.length} cancellable game(s):`);
|
|
122
|
+
result.rows.forEach(g => {
|
|
123
|
+
console.log(` - ${g.game_id} (status: ${g.game_status}, creator: ${g.creator_wallet?.slice(0, 8)}...)`);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
return result.rows[0];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Test cancelling a Connect4 game via API
|
|
131
|
+
*/
|
|
132
|
+
async function testCancelGame(gameId, creatorWallet) {
|
|
133
|
+
console.log(`\n📋 Test: Cancel Connect4 Game`);
|
|
134
|
+
console.log('------------------------------');
|
|
135
|
+
console.log(` Game ID: ${gameId}`);
|
|
136
|
+
console.log(` Creator: ${creatorWallet}`);
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
const authToken = await getTestAuthToken(creatorWallet);
|
|
140
|
+
console.log(` Auth token: ${authToken.slice(0, 20)}...`);
|
|
141
|
+
|
|
142
|
+
console.log(` Calling POST ${SERVER_URL}/api/connect4/cancel...`);
|
|
143
|
+
|
|
144
|
+
const response = await axios.post(
|
|
145
|
+
`${SERVER_URL}/api/connect4/cancel`,
|
|
146
|
+
{ gameId },
|
|
147
|
+
{
|
|
148
|
+
headers: {
|
|
149
|
+
'Authorization': `Bearer ${authToken}`,
|
|
150
|
+
'Content-Type': 'application/json'
|
|
151
|
+
},
|
|
152
|
+
timeout: 60000 // 60 second timeout for on-chain confirmation
|
|
153
|
+
}
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
console.log(` Response status: ${response.status}`);
|
|
157
|
+
console.log(` Response data: ${JSON.stringify(response.data, null, 2)}`);
|
|
158
|
+
|
|
159
|
+
if (response.data.success) {
|
|
160
|
+
console.log(`\n✅ CANCEL TEST PASSED`);
|
|
161
|
+
console.log(` Signature: ${response.data.signature || 'N/A'}`);
|
|
162
|
+
return { success: true, signature: response.data.signature };
|
|
163
|
+
} else {
|
|
164
|
+
console.log(`\n❌ CANCEL TEST FAILED: ${response.data.error || 'Unknown error'}`);
|
|
165
|
+
return { success: false, error: response.data.error };
|
|
166
|
+
}
|
|
167
|
+
} catch (error) {
|
|
168
|
+
const errorMsg = error.response?.data?.error || error.message;
|
|
169
|
+
console.error(`\n❌ CANCEL TEST FAILED: ${errorMsg}`);
|
|
170
|
+
|
|
171
|
+
if (error.response?.data) {
|
|
172
|
+
console.log(` Full response: ${JSON.stringify(error.response.data, null, 2)}`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return { success: false, error: errorMsg };
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Test claiming a Connect4 refund via API
|
|
181
|
+
*/
|
|
182
|
+
async function testClaimRefund(gameId, playerWallet) {
|
|
183
|
+
console.log(`\n📋 Test: Claim Connect4 Refund`);
|
|
184
|
+
console.log('-------------------------------');
|
|
185
|
+
console.log(` Game ID: ${gameId}`);
|
|
186
|
+
console.log(` Player: ${playerWallet}`);
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
const authToken = await getTestAuthToken(playerWallet);
|
|
190
|
+
console.log(` Auth token: ${authToken.slice(0, 20)}...`);
|
|
191
|
+
|
|
192
|
+
console.log(` Calling POST ${SERVER_URL}/api/connect4/claim...`);
|
|
193
|
+
|
|
194
|
+
const response = await axios.post(
|
|
195
|
+
`${SERVER_URL}/api/connect4/claim`,
|
|
196
|
+
{ gameId },
|
|
197
|
+
{
|
|
198
|
+
headers: {
|
|
199
|
+
'Authorization': `Bearer ${authToken}`,
|
|
200
|
+
'Content-Type': 'application/json'
|
|
201
|
+
},
|
|
202
|
+
timeout: 60000
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
console.log(` Response status: ${response.status}`);
|
|
207
|
+
console.log(` Response data: ${JSON.stringify(response.data, null, 2)}`);
|
|
208
|
+
|
|
209
|
+
if (response.data.success || response.data.transaction) {
|
|
210
|
+
console.log(`\n✅ CLAIM API TEST PASSED`);
|
|
211
|
+
console.log(` Transaction returned for user to sign`);
|
|
212
|
+
|
|
213
|
+
// The claim endpoint returns a transaction for the user to sign
|
|
214
|
+
// In a real test, we'd sign and send it
|
|
215
|
+
return { success: true, transaction: response.data.transaction };
|
|
216
|
+
} else {
|
|
217
|
+
console.log(`\n❌ CLAIM TEST FAILED: ${response.data.error || 'Unknown error'}`);
|
|
218
|
+
return { success: false, error: response.data.error };
|
|
219
|
+
}
|
|
220
|
+
} catch (error) {
|
|
221
|
+
const errorMsg = error.response?.data?.error || error.message;
|
|
222
|
+
console.error(`\n❌ CLAIM TEST FAILED: ${errorMsg}`);
|
|
223
|
+
|
|
224
|
+
if (error.response?.data) {
|
|
225
|
+
console.log(` Full response: ${JSON.stringify(error.response.data, null, 2)}`);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return { success: false, error: errorMsg };
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Verify game state in database
|
|
234
|
+
*/
|
|
235
|
+
async function verifyGameState(gameId) {
|
|
236
|
+
console.log(`\n📋 Verifying game state in database...`);
|
|
237
|
+
|
|
238
|
+
const result = await pool.query(`
|
|
239
|
+
SELECT
|
|
240
|
+
g.game_id, g.game_status, g.connect4_winner as winner, g.is_resolved,
|
|
241
|
+
g.claim_signature, g.buy_in,
|
|
242
|
+
creator.wallet_address as creator_wallet, creator.claimed_at
|
|
243
|
+
FROM games g
|
|
244
|
+
LEFT JOIN user_game_refs creator ON g.game_id = creator.game_id AND creator.role = 'creator'
|
|
245
|
+
WHERE g.game_id = $1
|
|
246
|
+
`, [gameId]);
|
|
247
|
+
|
|
248
|
+
if (result.rows.length === 0) {
|
|
249
|
+
console.log(` ❌ Game not found in database`);
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const game = result.rows[0];
|
|
254
|
+
console.log(` Game ID: ${game.game_id}`);
|
|
255
|
+
console.log(` Status: ${game.game_status}`);
|
|
256
|
+
console.log(` Winner: ${game.winner || 'null'}`);
|
|
257
|
+
console.log(` is_resolved: ${game.is_resolved}`);
|
|
258
|
+
console.log(` claimed_at: ${game.claimed_at || 'null'}`);
|
|
259
|
+
console.log(` claim_signature: ${game.claim_signature || 'null'}`);
|
|
260
|
+
console.log(` Creator: ${game.creator_wallet}`);
|
|
261
|
+
console.log(` Buy-in: ${game.buy_in}`);
|
|
262
|
+
|
|
263
|
+
return game;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Main test execution
|
|
268
|
+
*/
|
|
269
|
+
async function main() {
|
|
270
|
+
if (options.help) {
|
|
271
|
+
console.log('Usage:');
|
|
272
|
+
console.log(' node test-connect4-cancel-claim.js # Auto-find and test');
|
|
273
|
+
console.log(' node test-connect4-cancel-claim.js --cancel-only=<id> # Just cancel');
|
|
274
|
+
console.log(' node test-connect4-cancel-claim.js --claim-only=<id> # Just claim');
|
|
275
|
+
console.log(' node test-connect4-cancel-claim.js --game-id=<id> # Full flow on specific game');
|
|
276
|
+
process.exit(0);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
let passed = 0;
|
|
280
|
+
let failed = 0;
|
|
281
|
+
|
|
282
|
+
try {
|
|
283
|
+
// Test 1: Cancel only
|
|
284
|
+
if (options.cancelOnly) {
|
|
285
|
+
const game = await verifyGameState(options.cancelOnly);
|
|
286
|
+
if (game) {
|
|
287
|
+
const result = await testCancelGame(options.cancelOnly, game.creator_wallet);
|
|
288
|
+
if (result.success) passed++; else failed++;
|
|
289
|
+
await verifyGameState(options.cancelOnly);
|
|
290
|
+
} else {
|
|
291
|
+
failed++;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
// Test 2: Claim only
|
|
295
|
+
else if (options.claimOnly) {
|
|
296
|
+
const game = await verifyGameState(options.claimOnly);
|
|
297
|
+
if (game) {
|
|
298
|
+
const result = await testClaimRefund(options.claimOnly, game.creator_wallet);
|
|
299
|
+
if (result.success) passed++; else failed++;
|
|
300
|
+
await verifyGameState(options.claimOnly);
|
|
301
|
+
} else {
|
|
302
|
+
failed++;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
// Test 3: Full flow - find or use provided game
|
|
306
|
+
else {
|
|
307
|
+
// First, try to find a cancelled unclaimed game to test claim
|
|
308
|
+
let game = await findCancelledUnclaimedGame();
|
|
309
|
+
|
|
310
|
+
if (game) {
|
|
311
|
+
console.log(`\n🎯 Testing claim on cancelled game: ${game.game_id}`);
|
|
312
|
+
const claimResult = await testClaimRefund(game.game_id, game.creator_wallet);
|
|
313
|
+
if (claimResult.success) passed++; else failed++;
|
|
314
|
+
await verifyGameState(game.game_id);
|
|
315
|
+
} else {
|
|
316
|
+
console.log('\n⚠️ No cancelled unclaimed games found to test claim.');
|
|
317
|
+
|
|
318
|
+
// Try to find an active game to cancel first
|
|
319
|
+
const activeGame = await findActiveCancellableGame();
|
|
320
|
+
if (activeGame) {
|
|
321
|
+
console.log(`\n🎯 Testing cancel + claim flow on: ${activeGame.game_id}`);
|
|
322
|
+
|
|
323
|
+
// Cancel it
|
|
324
|
+
const cancelResult = await testCancelGame(activeGame.game_id, activeGame.creator_wallet);
|
|
325
|
+
if (cancelResult.success) {
|
|
326
|
+
passed++;
|
|
327
|
+
|
|
328
|
+
// Now test claim
|
|
329
|
+
const claimResult = await testClaimRefund(activeGame.game_id, activeGame.creator_wallet);
|
|
330
|
+
if (claimResult.success) passed++; else failed++;
|
|
331
|
+
} else {
|
|
332
|
+
failed++;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
await verifyGameState(activeGame.game_id);
|
|
336
|
+
} else {
|
|
337
|
+
console.log('\n⚠️ No games available for testing.');
|
|
338
|
+
console.log(' Create a Connect4 game first, then run this script.');
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Summary
|
|
344
|
+
console.log('\n=====================================');
|
|
345
|
+
console.log('📊 Test Summary');
|
|
346
|
+
console.log('=====================================');
|
|
347
|
+
console.log(` Passed: ${passed}`);
|
|
348
|
+
console.log(` Failed: ${failed}`);
|
|
349
|
+
console.log('');
|
|
350
|
+
|
|
351
|
+
if (failed === 0 && passed > 0) {
|
|
352
|
+
console.log('✅ All tests passed!');
|
|
353
|
+
} else if (passed === 0 && failed === 0) {
|
|
354
|
+
console.log('⚠️ No tests were run. Create a Connect4 game first.');
|
|
355
|
+
} else {
|
|
356
|
+
console.log('❌ Some tests failed. Check the output above.');
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
} catch (error) {
|
|
360
|
+
console.error('\n❌ Fatal error:', error.message);
|
|
361
|
+
console.error(error.stack);
|
|
362
|
+
failed++;
|
|
363
|
+
} finally {
|
|
364
|
+
await pool.end();
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
process.exit(failed > 0 ? 1 : 0);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
main();
|