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,91 @@
|
|
|
1
|
+
-- Retroactively award badges to users who have referrals but no badges
|
|
2
|
+
|
|
3
|
+
-- Get users who have referrals
|
|
4
|
+
WITH referral_counts AS (
|
|
5
|
+
SELECT
|
|
6
|
+
u.id as user_id,
|
|
7
|
+
u.my_referral_code,
|
|
8
|
+
COUNT(referred.id) as referral_count
|
|
9
|
+
FROM users u
|
|
10
|
+
LEFT JOIN users referred ON referred.referral_code = u.my_referral_code
|
|
11
|
+
WHERE u.my_referral_code IS NOT NULL
|
|
12
|
+
GROUP BY u.id, u.my_referral_code
|
|
13
|
+
)
|
|
14
|
+
-- Award badges based on thresholds
|
|
15
|
+
INSERT INTO user_badges (user_id, badge_type, badge_name, badge_description, badge_icon, referral_count)
|
|
16
|
+
SELECT
|
|
17
|
+
rc.user_id,
|
|
18
|
+
CASE
|
|
19
|
+
WHEN rc.referral_count >= 10 THEN 'captain'
|
|
20
|
+
WHEN rc.referral_count >= 5 THEN 'ambassador'
|
|
21
|
+
WHEN rc.referral_count >= 1 THEN 'recruiter'
|
|
22
|
+
END as badge_type,
|
|
23
|
+
CASE
|
|
24
|
+
WHEN rc.referral_count >= 10 THEN 'Captain'
|
|
25
|
+
WHEN rc.referral_count >= 5 THEN 'Ambassador'
|
|
26
|
+
WHEN rc.referral_count >= 1 THEN 'Recruiter'
|
|
27
|
+
END as badge_name,
|
|
28
|
+
CASE
|
|
29
|
+
WHEN rc.referral_count >= 10 THEN 'Referred 10 or more users'
|
|
30
|
+
WHEN rc.referral_count >= 5 THEN 'Referred 5 users'
|
|
31
|
+
WHEN rc.referral_count >= 1 THEN 'Referred your first user'
|
|
32
|
+
END as badge_description,
|
|
33
|
+
CASE
|
|
34
|
+
WHEN rc.referral_count >= 10 THEN '/badges/badge_2-removebg-preview.png'
|
|
35
|
+
WHEN rc.referral_count >= 5 THEN '/badges/badge_1-removebg-preview.png'
|
|
36
|
+
WHEN rc.referral_count >= 1 THEN '/badges/badge_0-removebg-preview.png'
|
|
37
|
+
END as badge_icon,
|
|
38
|
+
rc.referral_count
|
|
39
|
+
FROM referral_counts rc
|
|
40
|
+
WHERE rc.referral_count >= 1
|
|
41
|
+
ON CONFLICT (user_id, badge_type) DO UPDATE
|
|
42
|
+
SET referral_count = EXCLUDED.referral_count;
|
|
43
|
+
|
|
44
|
+
-- Award lower tier badges if user has higher tier
|
|
45
|
+
INSERT INTO user_badges (user_id, badge_type, badge_name, badge_description, badge_icon, referral_count)
|
|
46
|
+
SELECT DISTINCT
|
|
47
|
+
ub.user_id,
|
|
48
|
+
'recruiter',
|
|
49
|
+
'Recruiter',
|
|
50
|
+
'Referred your first user',
|
|
51
|
+
'/badges/badge_0-removebg-preview.png',
|
|
52
|
+
ub.referral_count
|
|
53
|
+
FROM user_badges ub
|
|
54
|
+
WHERE ub.badge_type IN ('ambassador', 'captain')
|
|
55
|
+
AND NOT EXISTS (
|
|
56
|
+
SELECT 1 FROM user_badges ub2
|
|
57
|
+
WHERE ub2.user_id = ub.user_id
|
|
58
|
+
AND ub2.badge_type = 'recruiter'
|
|
59
|
+
)
|
|
60
|
+
ON CONFLICT (user_id, badge_type) DO NOTHING;
|
|
61
|
+
|
|
62
|
+
-- Award ambassador badge if user has captain
|
|
63
|
+
INSERT INTO user_badges (user_id, badge_type, badge_name, badge_description, badge_icon, referral_count)
|
|
64
|
+
SELECT DISTINCT
|
|
65
|
+
ub.user_id,
|
|
66
|
+
'ambassador',
|
|
67
|
+
'Ambassador',
|
|
68
|
+
'Referred 5 users',
|
|
69
|
+
'/badges/badge_1-removebg-preview.png',
|
|
70
|
+
ub.referral_count
|
|
71
|
+
FROM user_badges ub
|
|
72
|
+
WHERE ub.badge_type = 'captain'
|
|
73
|
+
AND NOT EXISTS (
|
|
74
|
+
SELECT 1 FROM user_badges ub2
|
|
75
|
+
WHERE ub2.user_id = ub.user_id
|
|
76
|
+
AND ub2.badge_type = 'ambassador'
|
|
77
|
+
)
|
|
78
|
+
ON CONFLICT (user_id, badge_type) DO NOTHING;
|
|
79
|
+
|
|
80
|
+
-- Show results
|
|
81
|
+
SELECT
|
|
82
|
+
u.username,
|
|
83
|
+
u.wallet_address,
|
|
84
|
+
COUNT(referred.id) as referrals,
|
|
85
|
+
STRING_AGG(ub.badge_name, ', ') as badges
|
|
86
|
+
FROM users u
|
|
87
|
+
LEFT JOIN users referred ON referred.referral_code = u.my_referral_code
|
|
88
|
+
LEFT JOIN user_badges ub ON ub.user_id = u.id
|
|
89
|
+
WHERE u.my_referral_code IS NOT NULL
|
|
90
|
+
GROUP BY u.id, u.username, u.wallet_address
|
|
91
|
+
ORDER BY referrals DESC;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
-- Fix payment notification constraint on Heroku
|
|
2
|
+
-- Run this if payments aren't working after deployment
|
|
3
|
+
|
|
4
|
+
-- Drop the old constraint
|
|
5
|
+
ALTER TABLE chat_notifications
|
|
6
|
+
DROP CONSTRAINT IF EXISTS chat_notifications_notification_type_check;
|
|
7
|
+
|
|
8
|
+
-- Add new constraint with payment types
|
|
9
|
+
ALTER TABLE chat_notifications
|
|
10
|
+
ADD CONSTRAINT chat_notifications_notification_type_check
|
|
11
|
+
CHECK (notification_type IN (
|
|
12
|
+
'reply',
|
|
13
|
+
'mention',
|
|
14
|
+
'friend_message',
|
|
15
|
+
'reaction',
|
|
16
|
+
'friend_request',
|
|
17
|
+
'friend_request_accepted',
|
|
18
|
+
'friend_request_declined',
|
|
19
|
+
'referral',
|
|
20
|
+
'game_joined',
|
|
21
|
+
'game_invite',
|
|
22
|
+
'game_starting_soon',
|
|
23
|
+
'game_starting_now',
|
|
24
|
+
'payment_received',
|
|
25
|
+
'payment_sent'
|
|
26
|
+
));
|
|
27
|
+
|
|
28
|
+
-- Verify it worked
|
|
29
|
+
SELECT constraint_name, check_clause
|
|
30
|
+
FROM information_schema.check_constraints
|
|
31
|
+
WHERE constraint_name = 'chat_notifications_notification_type_check';
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// NUCLEAR OPTION: Force increment config round ID to skip stuck round
|
|
3
|
+
|
|
4
|
+
const { Connection, Keypair, PublicKey, Transaction, TransactionInstruction } = require('@solana/web3.js');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
8
|
+
const RPC_URL = 'https://api.devnet.solana.com';
|
|
9
|
+
const PROGRAM_ID = new PublicKey('BHidyz25KWkNPdTHgeANzMg25MM2KEiNnG4yE5F46XUz');
|
|
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('💣 NUCLEAR OPTION: Opening round 98 to skip 97');
|
|
17
|
+
|
|
18
|
+
const connection = new Connection(RPC_URL, 'confirmed');
|
|
19
|
+
|
|
20
|
+
const [configPda] = PublicKey.findProgramAddressSync([Buffer.from('config')], PROGRAM_ID);
|
|
21
|
+
const [round98Pda] = PublicKey.findProgramAddressSync([Buffer.from('round'), Buffer.from([98,0,0,0,0,0,0,0])], PROGRAM_ID);
|
|
22
|
+
const [entries98Pda] = PublicKey.findProgramAddressSync([Buffer.from('entries'), Buffer.from([98,0,0,0,0,0,0,0])], PROGRAM_ID);
|
|
23
|
+
|
|
24
|
+
const OPEN_ROUND = Buffer.from([66, 235, 123, 240, 8, 35, 185, 159]);
|
|
25
|
+
|
|
26
|
+
const ix = new TransactionInstruction({
|
|
27
|
+
keys: [
|
|
28
|
+
{ pubkey: configPda, isSigner: false, isWritable: true },
|
|
29
|
+
{ pubkey: round98Pda, isSigner: false, isWritable: true },
|
|
30
|
+
{ pubkey: entries98Pda, isSigner: false, isWritable: true },
|
|
31
|
+
{ pubkey: wallet.publicKey, isSigner: true, isWritable: true },
|
|
32
|
+
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
33
|
+
],
|
|
34
|
+
programId: PROGRAM_ID,
|
|
35
|
+
data: OPEN_ROUND,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const tx = new Transaction().add(ix);
|
|
39
|
+
tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
|
|
40
|
+
tx.feePayer = wallet.publicKey;
|
|
41
|
+
tx.sign(wallet);
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const sig = await connection.sendRawTransaction(tx.serialize());
|
|
45
|
+
console.log('Sig:', sig);
|
|
46
|
+
await connection.confirmTransaction(sig);
|
|
47
|
+
console.log('✅ Round 98 opened! System should be unstuck now!');
|
|
48
|
+
} catch (e) {
|
|
49
|
+
console.error('❌', e.message);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const { SystemProgram } = require('@solana/web3.js');
|
|
54
|
+
main();
|
|
55
|
+
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Force Resolve and Claim Script
|
|
4
|
+
* Resolves stuck games and claims refunds directly using on-chain data
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* node force-resolve-and-claim.js
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
require('dotenv').config();
|
|
11
|
+
const {
|
|
12
|
+
Connection,
|
|
13
|
+
PublicKey,
|
|
14
|
+
Keypair,
|
|
15
|
+
Transaction,
|
|
16
|
+
TransactionInstruction,
|
|
17
|
+
sendAndConfirmTransaction,
|
|
18
|
+
LAMPORTS_PER_SOL
|
|
19
|
+
} = require('@solana/web3.js');
|
|
20
|
+
const fs = require('fs');
|
|
21
|
+
const path = require('path');
|
|
22
|
+
|
|
23
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
24
|
+
// CONFIGURATION - Update these values!
|
|
25
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
26
|
+
|
|
27
|
+
// The stuck games to recover (from on-chain analysis)
|
|
28
|
+
const STUCK_GAMES = [
|
|
29
|
+
{
|
|
30
|
+
pda: 'FrggqLKgxdiTLybXK3fU8qpFG7YPtyh6fP2Y5onYWGhq',
|
|
31
|
+
gameId: BigInt('16210635126547177265'),
|
|
32
|
+
player: 'FWUJCthDfPcgmTvdQWM5uofxxiYjqJFMMwiLYvS7LBFa',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
pda: 'DQGXTTewkW6QSSWTgaGTS8naepD6yDBumRRezhnpRkLK',
|
|
36
|
+
gameId: BigInt('13313520635794528485'),
|
|
37
|
+
player: 'FWUJCthDfPcgmTvdQWM5uofxxiYjqJFMMwiLYvS7LBFa',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
pda: '6Bhvh1f9H1X3VMigVXLQNKoxCUftcTcnMCPGqzX4aBY',
|
|
41
|
+
gameId: BigInt('4788170354430293005'),
|
|
42
|
+
player: 'FWUJCthDfPcgmTvdQWM5uofxxiYjqJFMMwiLYvS7LBFa',
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
// Program ID (mainnet)
|
|
47
|
+
const PROGRAM_ID = new PublicKey('85wJGp9uc8w2FeKX9CEHsudTo1UVCrmuRFy37oCcaoG1');
|
|
48
|
+
|
|
49
|
+
// Hardcoded operator wallet (from program)
|
|
50
|
+
const OPERATOR_WALLET = new PublicKey('BVZXwZpfgyzTBdRFHohkHZppPHnAyqyctRsKy3vWfQib');
|
|
51
|
+
|
|
52
|
+
// Instruction discriminators (calculated from Anchor)
|
|
53
|
+
const RESOLVE_AUTO_DISCRIMINATOR = Buffer.from([245, 33, 115, 150, 82, 150, 28, 193]);
|
|
54
|
+
const CLAIM_AUTO_DISCRIMINATOR = Buffer.from([8, 125, 228, 42, 245, 90, 82, 17]);
|
|
55
|
+
|
|
56
|
+
// RPC endpoint - use Alchemy for reliability
|
|
57
|
+
const RPC_URL = process.env.SOLANA_RPC_URL || 'https://api.mainnet-beta.solana.com';
|
|
58
|
+
|
|
59
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
60
|
+
|
|
61
|
+
console.log('🔧 Force Resolve and Claim Tool');
|
|
62
|
+
console.log('================================');
|
|
63
|
+
console.log(`RPC: ${RPC_URL}`);
|
|
64
|
+
console.log(`Program: ${PROGRAM_ID.toString()}`);
|
|
65
|
+
console.log('');
|
|
66
|
+
|
|
67
|
+
const connection = new Connection(RPC_URL, 'confirmed');
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Load oracle wallet from environment or file
|
|
71
|
+
*/
|
|
72
|
+
function loadOracleWallet() {
|
|
73
|
+
// Try environment variable first
|
|
74
|
+
if (process.env.ORACLE_WALLET_JSON) {
|
|
75
|
+
console.log('🔑 Loading oracle wallet from ORACLE_WALLET_JSON env var');
|
|
76
|
+
const secretKey = JSON.parse(process.env.ORACLE_WALLET_JSON);
|
|
77
|
+
return Keypair.fromSecretKey(Uint8Array.from(secretKey));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Try file path
|
|
81
|
+
const walletPath = process.env.ORACLE_WALLET_PATH || path.join(__dirname, 'wallets/oracle.json');
|
|
82
|
+
|
|
83
|
+
if (fs.existsSync(walletPath)) {
|
|
84
|
+
console.log('🔑 Loading oracle wallet from:', walletPath);
|
|
85
|
+
const secretKey = JSON.parse(fs.readFileSync(walletPath, 'utf-8'));
|
|
86
|
+
return Keypair.fromSecretKey(Uint8Array.from(secretKey));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
console.error('❌ Oracle wallet not found!');
|
|
90
|
+
console.log(' Set ORACLE_WALLET_JSON env var or create wallets/oracle.json');
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Build resolve_automatic_game instruction
|
|
96
|
+
* Sets winning_team to None (0 option tag) for refund
|
|
97
|
+
*/
|
|
98
|
+
function buildResolveInstruction(gamePda, gameId, oracleWallet) {
|
|
99
|
+
// Instruction data: discriminator (8) + game_id (8) + winning_team Option (1 byte = None)
|
|
100
|
+
const gameIdBuf = Buffer.alloc(8);
|
|
101
|
+
gameIdBuf.writeBigUInt64LE(gameId);
|
|
102
|
+
|
|
103
|
+
// Option<TeamChoice>: 0 = None (refund all)
|
|
104
|
+
const winningTeamBuf = Buffer.from([0]); // None variant
|
|
105
|
+
|
|
106
|
+
const data = Buffer.concat([
|
|
107
|
+
RESOLVE_AUTO_DISCRIMINATOR,
|
|
108
|
+
gameIdBuf,
|
|
109
|
+
winningTeamBuf,
|
|
110
|
+
]);
|
|
111
|
+
|
|
112
|
+
return new TransactionInstruction({
|
|
113
|
+
keys: [
|
|
114
|
+
{ pubkey: new PublicKey(gamePda), isSigner: false, isWritable: true },
|
|
115
|
+
{ pubkey: oracleWallet.publicKey, isSigner: true, isWritable: true },
|
|
116
|
+
{ pubkey: OPERATOR_WALLET, isSigner: false, isWritable: true }, // Receives operator fee
|
|
117
|
+
],
|
|
118
|
+
programId: PROGRAM_ID,
|
|
119
|
+
data,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Build claim_automatic_winnings instruction
|
|
125
|
+
*/
|
|
126
|
+
function buildClaimInstruction(gamePda, gameId, playerWallet) {
|
|
127
|
+
// Instruction data: discriminator (8) + game_id (8)
|
|
128
|
+
const gameIdBuf = Buffer.alloc(8);
|
|
129
|
+
gameIdBuf.writeBigUInt64LE(gameId);
|
|
130
|
+
|
|
131
|
+
const data = Buffer.concat([
|
|
132
|
+
CLAIM_AUTO_DISCRIMINATOR,
|
|
133
|
+
gameIdBuf,
|
|
134
|
+
]);
|
|
135
|
+
|
|
136
|
+
return new TransactionInstruction({
|
|
137
|
+
keys: [
|
|
138
|
+
{ pubkey: new PublicKey(gamePda), isSigner: false, isWritable: true },
|
|
139
|
+
{ pubkey: new PublicKey(playerWallet), isSigner: true, isWritable: true },
|
|
140
|
+
],
|
|
141
|
+
programId: PROGRAM_ID,
|
|
142
|
+
data,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Poll for transaction confirmation (Agave 2.0 compatible)
|
|
148
|
+
*/
|
|
149
|
+
async function confirmTransaction(signature, timeout = 60000) {
|
|
150
|
+
const start = Date.now();
|
|
151
|
+
|
|
152
|
+
while (Date.now() - start < timeout) {
|
|
153
|
+
const statuses = await connection.getSignatureStatuses([signature]);
|
|
154
|
+
const status = statuses?.value?.[0];
|
|
155
|
+
|
|
156
|
+
if (status?.err) {
|
|
157
|
+
throw new Error(`Transaction failed: ${JSON.stringify(status.err)}`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (status?.confirmationStatus === 'confirmed' || status?.confirmationStatus === 'finalized') {
|
|
161
|
+
return status;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
throw new Error('Transaction confirmation timeout');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Resolve a single game
|
|
172
|
+
*/
|
|
173
|
+
async function resolveGame(game, oracleWallet) {
|
|
174
|
+
console.log(`\n📍 Resolving game: ${game.pda}`);
|
|
175
|
+
console.log(` Game ID: ${game.gameId.toString()}`);
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
const ix = buildResolveInstruction(game.pda, game.gameId, oracleWallet);
|
|
179
|
+
const tx = new Transaction().add(ix);
|
|
180
|
+
|
|
181
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();
|
|
182
|
+
tx.recentBlockhash = blockhash;
|
|
183
|
+
tx.feePayer = oracleWallet.publicKey;
|
|
184
|
+
|
|
185
|
+
// Sign FIRST before sending
|
|
186
|
+
tx.sign(oracleWallet);
|
|
187
|
+
|
|
188
|
+
console.log(' 📡 Sending resolve transaction...');
|
|
189
|
+
const signature = await connection.sendRawTransaction(tx.serialize(), {
|
|
190
|
+
skipPreflight: false,
|
|
191
|
+
preflightCommitment: 'confirmed',
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
console.log(` 📝 Signature: ${signature}`);
|
|
195
|
+
console.log(' ⏳ Confirming...');
|
|
196
|
+
await confirmTransaction(signature);
|
|
197
|
+
|
|
198
|
+
console.log(` ✅ Resolved!`);
|
|
199
|
+
return signature;
|
|
200
|
+
|
|
201
|
+
} catch (error) {
|
|
202
|
+
// Try to get logs for more details
|
|
203
|
+
if (error.logs) {
|
|
204
|
+
console.error(' 📋 Logs:', error.logs.join('\n '));
|
|
205
|
+
}
|
|
206
|
+
if (error.message?.includes('AlreadyResolved')) {
|
|
207
|
+
console.log(' ℹ️ Game already resolved');
|
|
208
|
+
return 'already_resolved';
|
|
209
|
+
}
|
|
210
|
+
if (error.message?.includes('CannotResolveBeforeLockTime')) {
|
|
211
|
+
console.log(' ⏰ Cannot resolve before lock time (game hasn\'t started yet)');
|
|
212
|
+
return 'too_early';
|
|
213
|
+
}
|
|
214
|
+
console.error(` ❌ Error: ${error.message}`);
|
|
215
|
+
throw error;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Main execution
|
|
221
|
+
*/
|
|
222
|
+
async function main() {
|
|
223
|
+
const args = process.argv.slice(2);
|
|
224
|
+
|
|
225
|
+
console.log('📊 Games to recover:');
|
|
226
|
+
STUCK_GAMES.forEach((game, i) => {
|
|
227
|
+
console.log(` ${i + 1}. PDA: ${game.pda.slice(0, 12)}... | Player: ${game.player.slice(0, 12)}...`);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Check if --resolve flag is passed
|
|
231
|
+
if (args.includes('--resolve')) {
|
|
232
|
+
console.log('\n🔐 Loading oracle wallet...');
|
|
233
|
+
const oracleWallet = loadOracleWallet();
|
|
234
|
+
console.log(` Oracle: ${oracleWallet.publicKey.toString()}`);
|
|
235
|
+
|
|
236
|
+
// Verify oracle matches expected
|
|
237
|
+
const expectedOracle = 'FWUJCthDfPcgmTvdQWM5uofxxiYjqJFMMwiLYvS7LBFa';
|
|
238
|
+
if (oracleWallet.publicKey.toString() !== expectedOracle) {
|
|
239
|
+
console.error(` ⚠️ Warning: Oracle doesn't match expected (${expectedOracle})`);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
console.log('\n🔧 Resolving games...');
|
|
243
|
+
|
|
244
|
+
for (const game of STUCK_GAMES) {
|
|
245
|
+
try {
|
|
246
|
+
await resolveGame(game, oracleWallet);
|
|
247
|
+
} catch (error) {
|
|
248
|
+
console.error(` Failed to resolve ${game.pda}: ${error.message}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
console.log('\n✅ Resolution complete!');
|
|
253
|
+
console.log('💡 Now use the frontend to claim your refunds, or run:');
|
|
254
|
+
console.log(' node force-resolve-and-claim.js --claim <playerWalletPath>');
|
|
255
|
+
|
|
256
|
+
} else if (args.includes('--claim')) {
|
|
257
|
+
// For claiming, the player needs to sign
|
|
258
|
+
console.log('\n💰 Claim mode');
|
|
259
|
+
console.log(' To claim, use the frontend "Claim" button in My Games');
|
|
260
|
+
console.log(' Or call the API: POST /api/v1/prod/transaction/build/claim-automatic');
|
|
261
|
+
console.log(' With body: { "playerAddress": "<wallet>", "gameId": "<gameId>" }');
|
|
262
|
+
|
|
263
|
+
} else {
|
|
264
|
+
console.log('\nUsage:');
|
|
265
|
+
console.log(' node force-resolve-and-claim.js --resolve # Resolve all stuck games (requires oracle wallet)');
|
|
266
|
+
console.log(' node force-resolve-and-claim.js --claim # Show claim instructions');
|
|
267
|
+
console.log('');
|
|
268
|
+
console.log('Prerequisites:');
|
|
269
|
+
console.log(' 1. Set ORACLE_WALLET_JSON env var with oracle private key array');
|
|
270
|
+
console.log(' OR create wallets/oracle.json with the keypair');
|
|
271
|
+
console.log(' 2. Oracle must match the one registered in the game accounts');
|
|
272
|
+
console.log('');
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
main().catch(console.error);
|
|
277
|
+
|
|
278
|
+
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Important Scripts
|
|
2
|
+
|
|
3
|
+
Scripts for managing games, payouts, and emergency operations.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## check-game-status.js
|
|
8
|
+
|
|
9
|
+
Shows complete game status including all players, their bets, win/loss results, claim status, and expected payouts.
|
|
10
|
+
|
|
11
|
+
**Usage:**
|
|
12
|
+
```bash
|
|
13
|
+
DATABASE_URL=$(heroku config:get DATABASE_URL -a dubs-server-prod) node scripts/important/check-game-status.js <gameId>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**Example:**
|
|
17
|
+
```bash
|
|
18
|
+
DATABASE_URL=$(heroku config:get DATABASE_URL -a dubs-server-prod) node scripts/important/check-game-status.js sport-1769102132440-xmirk1omx
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Output includes:**
|
|
22
|
+
- Game info (teams, score, winner, buy-in, resolved status)
|
|
23
|
+
- Pot breakdown (total pot, platform fee, winner pool)
|
|
24
|
+
- Player table with bets, results, claim status, and payouts
|
|
25
|
+
- Claim transaction signatures and explorer links
|
|
26
|
+
- Summary of pending claims
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## reconcile-v1-v2-payouts.js
|
|
31
|
+
|
|
32
|
+
Calculates the difference between V1 (equal split) and V2 (proportional) payouts for any game. Shows what you would owe players to make V1 payouts fair under V2 rules.
|
|
33
|
+
|
|
34
|
+
**Usage:**
|
|
35
|
+
```bash
|
|
36
|
+
DATABASE_URL=$(heroku config:get DATABASE_URL -a dubs-server-prod) node scripts/important/reconcile-v1-v2-payouts.js <gameId>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Output includes:**
|
|
40
|
+
- Pot details and team pools
|
|
41
|
+
- Scenarios for each possible winner (home/away/draw)
|
|
42
|
+
- Per-player breakdown: V1 payout vs V2 payout vs difference owed
|
|
43
|
+
- Total reconciliation amount needed
|
|
44
|
+
- If game is resolved: specific players and wallets to reimburse
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## list-pending-games-by-version.js
|
|
49
|
+
|
|
50
|
+
Lists all pending (unresolved) games categorized by version:
|
|
51
|
+
- **V1 (Legacy/Hybrid):** Equal split payouts - `player_amounts.length != total_players`
|
|
52
|
+
- **V2 (Pari-Mutuel):** Proportional payouts - all players in `player_amounts`
|
|
53
|
+
|
|
54
|
+
**Usage:**
|
|
55
|
+
```bash
|
|
56
|
+
DATABASE_URL=$(heroku config:get DATABASE_URL -a dubs-server-prod) node scripts/important/list-pending-games-by-version.js
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Output includes:**
|
|
60
|
+
- Games grouped by V1 vs V2
|
|
61
|
+
- Per-game details: matchup, pot size, team pools, odds
|
|
62
|
+
- Player list with bets and expected payouts
|
|
63
|
+
- Summary totals
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## authority-force-lock.js
|
|
68
|
+
|
|
69
|
+
Forces a game to locked state using program authority. This allows the oracle to resolve games that were created with future lock times (e.g., timezone issues, events ending early).
|
|
70
|
+
|
|
71
|
+
**Usage:**
|
|
72
|
+
```bash
|
|
73
|
+
SOLANA_RPC_URL="https://solana-mainnet.g.alchemy.com/v2/YOUR_KEY" node scripts/important/authority-force-lock.js <gameId>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**When to use:**
|
|
77
|
+
- Oracle shows "CannotResolveBeforeLockTime" error
|
|
78
|
+
- Game event has ended but lock time is in the future
|
|
79
|
+
- Need to manually trigger resolution
|
|
80
|
+
|
|
81
|
+
**Requirements:**
|
|
82
|
+
- Program authority wallet at `~/.config/solana/id.json`
|
|
83
|
+
- Mainnet RPC URL
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## authority-resolve-game.js
|
|
88
|
+
|
|
89
|
+
Emergency resolve or refund games using program authority. Can force resolve with a winner or refund all players.
|
|
90
|
+
|
|
91
|
+
**Usage:**
|
|
92
|
+
```bash
|
|
93
|
+
SOLANA_RPC_URL="https://solana-mainnet.g.alchemy.com/v2/YOUR_KEY" node scripts/important/authority-resolve-game.js <gameId> [winner]
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Examples:**
|
|
97
|
+
```bash
|
|
98
|
+
# Refund all players (no winner)
|
|
99
|
+
node scripts/important/authority-resolve-game.js sport-123
|
|
100
|
+
|
|
101
|
+
# Resolve with home team winning
|
|
102
|
+
node scripts/important/authority-resolve-game.js sport-123 home
|
|
103
|
+
|
|
104
|
+
# Resolve with away team winning
|
|
105
|
+
node scripts/important/authority-resolve-game.js sport-123 away
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**When to use:**
|
|
109
|
+
- Postponed or cancelled games that need refunding
|
|
110
|
+
- Stuck games where oracle failed
|
|
111
|
+
- Disputed games requiring manual resolution
|
|
112
|
+
|
|
113
|
+
**Requirements:**
|
|
114
|
+
- Program authority wallet at `~/.config/solana/id.json`
|
|
115
|
+
- Mainnet RPC URL
|