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,331 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🎰 Jackpot History Service (Postgres)
|
|
3
|
+
*
|
|
4
|
+
* Tracks round results in Heroku Postgres database
|
|
5
|
+
* NOTE: Gracefully degrades when DATABASE_URL is not set (local dev)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { pool } = require('./db'); // Shared database pool
|
|
9
|
+
|
|
10
|
+
class JackpotHistory {
|
|
11
|
+
constructor() {
|
|
12
|
+
// Check if database is configured
|
|
13
|
+
this.enabled = !!process.env.DATABASE_URL;
|
|
14
|
+
|
|
15
|
+
// In-memory storage for local dev (fallback when no DATABASE_URL)
|
|
16
|
+
this.memoryRounds = [];
|
|
17
|
+
this.lastWinnerMemory = null;
|
|
18
|
+
|
|
19
|
+
if (this.enabled) {
|
|
20
|
+
// Use shared pool from services/db.js
|
|
21
|
+
this.pool = pool;
|
|
22
|
+
|
|
23
|
+
// Initialize table on startup
|
|
24
|
+
this.initializeTable();
|
|
25
|
+
} else {
|
|
26
|
+
console.log('⚠️ Jackpot history: No DATABASE_URL set - using in-memory storage (local dev mode)');
|
|
27
|
+
this.pool = null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Helper to check if DB operations should run
|
|
32
|
+
_shouldRun() {
|
|
33
|
+
return this.enabled && this.pool;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async initializeTable() {
|
|
37
|
+
if (!this._shouldRun()) return;
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
await this.pool.query(`
|
|
41
|
+
CREATE TABLE IF NOT EXISTS jackpot_rounds (
|
|
42
|
+
id SERIAL PRIMARY KEY,
|
|
43
|
+
round_id VARCHAR(50) UNIQUE NOT NULL,
|
|
44
|
+
winner VARCHAR(100) NOT NULL,
|
|
45
|
+
win_amount VARCHAR(50) NOT NULL,
|
|
46
|
+
total_pot VARCHAR(50) NOT NULL,
|
|
47
|
+
entry_count INTEGER NOT NULL,
|
|
48
|
+
timestamp TIMESTAMP DEFAULT NOW(),
|
|
49
|
+
signature VARCHAR(200),
|
|
50
|
+
server_seed TEXT,
|
|
51
|
+
server_seed_hash TEXT,
|
|
52
|
+
oracle_seed TEXT,
|
|
53
|
+
created_at TIMESTAMP DEFAULT NOW()
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
CREATE INDEX IF NOT EXISTS idx_round_id ON jackpot_rounds(round_id);
|
|
57
|
+
CREATE INDEX IF NOT EXISTS idx_timestamp ON jackpot_rounds(timestamp DESC);
|
|
58
|
+
|
|
59
|
+
CREATE TABLE IF NOT EXISTS jackpot_entries (
|
|
60
|
+
id SERIAL PRIMARY KEY,
|
|
61
|
+
wallet_address VARCHAR(64) NOT NULL,
|
|
62
|
+
round_id VARCHAR(32) NOT NULL,
|
|
63
|
+
amount BIGINT NOT NULL,
|
|
64
|
+
transaction_signature VARCHAR(128) NOT NULL,
|
|
65
|
+
created_at TIMESTAMP DEFAULT NOW()
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
CREATE INDEX IF NOT EXISTS idx_jackpot_entries_wallet ON jackpot_entries(wallet_address);
|
|
69
|
+
CREATE INDEX IF NOT EXISTS idx_jackpot_entries_sig ON jackpot_entries(transaction_signature);
|
|
70
|
+
`);
|
|
71
|
+
|
|
72
|
+
// Migrate: add VRF columns if table existed before they were added
|
|
73
|
+
const cols = ['timestamp', 'signature', 'server_seed', 'server_seed_hash', 'oracle_seed'];
|
|
74
|
+
for (const col of cols) {
|
|
75
|
+
try {
|
|
76
|
+
const type = col === 'timestamp' ? 'TIMESTAMP DEFAULT NOW()'
|
|
77
|
+
: col === 'signature' ? 'VARCHAR(200)'
|
|
78
|
+
: 'TEXT';
|
|
79
|
+
await this.pool.query(`ALTER TABLE jackpot_rounds ADD COLUMN IF NOT EXISTS ${col} ${type}`);
|
|
80
|
+
} catch (e) {
|
|
81
|
+
// Column already exists — safe to ignore
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
console.log('✅ Jackpot history table initialized');
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.error('❌ Failed to initialize table:', error.message);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async getHistory() {
|
|
92
|
+
// Fallback to in-memory storage for local dev
|
|
93
|
+
if (!this._shouldRun()) {
|
|
94
|
+
return { rounds: this.memoryRounds.slice().reverse().slice(0, 100) };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
const result = await this.pool.query(
|
|
99
|
+
'SELECT * FROM jackpot_rounds ORDER BY timestamp DESC LIMIT 100'
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
rounds: result.rows.map(row => ({
|
|
104
|
+
roundId: row.round_id,
|
|
105
|
+
winner: row.winner,
|
|
106
|
+
winAmount: row.win_amount,
|
|
107
|
+
totalPot: row.total_pot,
|
|
108
|
+
entryCount: row.entry_count,
|
|
109
|
+
timestamp: row.timestamp,
|
|
110
|
+
signature: row.signature,
|
|
111
|
+
serverSeed: row.server_seed,
|
|
112
|
+
serverSeedHash: row.server_seed_hash,
|
|
113
|
+
oracleSeed: row.oracle_seed,
|
|
114
|
+
}))
|
|
115
|
+
};
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error('Error getting history:', error);
|
|
118
|
+
return { rounds: [] };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async addRound(roundData) {
|
|
123
|
+
const normalizedData = {
|
|
124
|
+
roundId: roundData.roundId,
|
|
125
|
+
winner: roundData.winner,
|
|
126
|
+
winAmount: roundData.winAmount,
|
|
127
|
+
totalPot: roundData.totalPot,
|
|
128
|
+
entryCount: roundData.entryCount,
|
|
129
|
+
timestamp: roundData.timestamp || new Date().toISOString(),
|
|
130
|
+
signature: roundData.signature || null,
|
|
131
|
+
serverSeed: roundData.serverSeed || null,
|
|
132
|
+
serverSeedHash: roundData.serverSeedHash || null,
|
|
133
|
+
oracleSeed: roundData.oracleSeed || null,
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// Always update in-memory storage (for local dev fallback)
|
|
137
|
+
this.memoryRounds.push(normalizedData);
|
|
138
|
+
this.lastWinnerMemory = normalizedData;
|
|
139
|
+
console.log(`📝 [Memory] Saved round ${roundData.roundId} - Winner: ${roundData.winner.slice(0,8)}...`);
|
|
140
|
+
|
|
141
|
+
if (!this._shouldRun()) return;
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
await this.pool.query(
|
|
145
|
+
`INSERT INTO jackpot_rounds
|
|
146
|
+
(round_id, winner, win_amount, total_pot, entry_count, timestamp, signature, server_seed, server_seed_hash, oracle_seed)
|
|
147
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
|
148
|
+
ON CONFLICT (round_id) DO UPDATE SET
|
|
149
|
+
winner = EXCLUDED.winner,
|
|
150
|
+
win_amount = EXCLUDED.win_amount,
|
|
151
|
+
total_pot = EXCLUDED.total_pot,
|
|
152
|
+
entry_count = EXCLUDED.entry_count,
|
|
153
|
+
timestamp = EXCLUDED.timestamp,
|
|
154
|
+
signature = EXCLUDED.signature,
|
|
155
|
+
server_seed = EXCLUDED.server_seed,
|
|
156
|
+
server_seed_hash = EXCLUDED.server_seed_hash,
|
|
157
|
+
oracle_seed = EXCLUDED.oracle_seed`,
|
|
158
|
+
[
|
|
159
|
+
normalizedData.roundId,
|
|
160
|
+
normalizedData.winner,
|
|
161
|
+
normalizedData.winAmount,
|
|
162
|
+
normalizedData.totalPot,
|
|
163
|
+
normalizedData.entryCount,
|
|
164
|
+
normalizedData.timestamp,
|
|
165
|
+
normalizedData.signature,
|
|
166
|
+
normalizedData.serverSeed,
|
|
167
|
+
normalizedData.serverSeedHash,
|
|
168
|
+
normalizedData.oracleSeed,
|
|
169
|
+
]
|
|
170
|
+
);
|
|
171
|
+
console.log(`📝 [DB] Saved round ${roundData.roundId} to history`);
|
|
172
|
+
} catch (error) {
|
|
173
|
+
console.error('Error adding round to DB:', error);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async getLastWinner() {
|
|
178
|
+
// Fallback to in-memory storage for local dev
|
|
179
|
+
if (!this._shouldRun()) {
|
|
180
|
+
return this.lastWinnerMemory;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
const result = await this.pool.query(
|
|
185
|
+
'SELECT * FROM jackpot_rounds ORDER BY timestamp DESC LIMIT 1'
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
if (result.rows.length === 0) return null;
|
|
189
|
+
|
|
190
|
+
const row = result.rows[0];
|
|
191
|
+
return {
|
|
192
|
+
roundId: row.round_id,
|
|
193
|
+
winner: row.winner,
|
|
194
|
+
winAmount: row.win_amount,
|
|
195
|
+
totalPot: row.total_pot,
|
|
196
|
+
entryCount: row.entry_count,
|
|
197
|
+
timestamp: row.timestamp,
|
|
198
|
+
signature: row.signature,
|
|
199
|
+
serverSeed: row.server_seed,
|
|
200
|
+
serverSeedHash: row.server_seed_hash,
|
|
201
|
+
oracleSeed: row.oracle_seed,
|
|
202
|
+
};
|
|
203
|
+
} catch (error) {
|
|
204
|
+
console.error('Error getting last winner:', error);
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async getRound(roundId) {
|
|
210
|
+
if (!this._shouldRun()) return null;
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
const result = await this.pool.query(
|
|
214
|
+
'SELECT * FROM jackpot_rounds WHERE round_id = $1',
|
|
215
|
+
[roundId.toString()]
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
if (result.rows.length === 0) return null;
|
|
219
|
+
|
|
220
|
+
const row = result.rows[0];
|
|
221
|
+
return {
|
|
222
|
+
roundId: row.round_id,
|
|
223
|
+
winner: row.winner,
|
|
224
|
+
winAmount: row.win_amount,
|
|
225
|
+
totalPot: row.total_pot,
|
|
226
|
+
entryCount: row.entry_count,
|
|
227
|
+
timestamp: row.timestamp,
|
|
228
|
+
signature: row.signature,
|
|
229
|
+
serverSeed: row.server_seed,
|
|
230
|
+
serverSeedHash: row.server_seed_hash,
|
|
231
|
+
oracleSeed: row.oracle_seed,
|
|
232
|
+
};
|
|
233
|
+
} catch (error) {
|
|
234
|
+
console.error('Error getting round:', error);
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async addEntry({ walletAddress, roundId, amount, signature }) {
|
|
240
|
+
if (!this._shouldRun()) return;
|
|
241
|
+
|
|
242
|
+
try {
|
|
243
|
+
await this.pool.query(
|
|
244
|
+
`INSERT INTO jackpot_entries (wallet_address, round_id, amount, transaction_signature)
|
|
245
|
+
VALUES ($1, $2, $3, $4)
|
|
246
|
+
ON CONFLICT DO NOTHING`,
|
|
247
|
+
[walletAddress, roundId.toString(), amount, signature]
|
|
248
|
+
);
|
|
249
|
+
console.log(`📝 [DB] Saved jackpot entry for ${walletAddress.slice(0, 8)}... in round ${roundId}`);
|
|
250
|
+
} catch (error) {
|
|
251
|
+
console.error('Error saving jackpot entry:', error);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
async getEntriesByWallet(walletAddress) {
|
|
256
|
+
if (!this._shouldRun()) return [];
|
|
257
|
+
|
|
258
|
+
try {
|
|
259
|
+
const result = await this.pool.query(
|
|
260
|
+
`SELECT round_id, amount, transaction_signature, created_at
|
|
261
|
+
FROM jackpot_entries
|
|
262
|
+
WHERE wallet_address = $1
|
|
263
|
+
ORDER BY created_at DESC
|
|
264
|
+
LIMIT 200`,
|
|
265
|
+
[walletAddress]
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
return result.rows.map(row => ({
|
|
269
|
+
roundId: row.round_id,
|
|
270
|
+
amount: row.amount.toString(),
|
|
271
|
+
signature: row.transaction_signature,
|
|
272
|
+
createdAt: row.created_at,
|
|
273
|
+
}));
|
|
274
|
+
} catch (error) {
|
|
275
|
+
console.error('Error getting jackpot entries by wallet:', error);
|
|
276
|
+
return [];
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
async getWinsByWallet(walletAddress) {
|
|
281
|
+
if (!this._shouldRun()) return [];
|
|
282
|
+
|
|
283
|
+
try {
|
|
284
|
+
const result = await this.pool.query(
|
|
285
|
+
`SELECT round_id, win_amount, total_pot, entry_count, signature, timestamp
|
|
286
|
+
FROM jackpot_rounds
|
|
287
|
+
WHERE winner = $1
|
|
288
|
+
ORDER BY timestamp DESC
|
|
289
|
+
LIMIT 200`,
|
|
290
|
+
[walletAddress]
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
return result.rows.map(row => ({
|
|
294
|
+
roundId: row.round_id,
|
|
295
|
+
winAmount: row.win_amount,
|
|
296
|
+
totalPot: row.total_pot,
|
|
297
|
+
entryCount: row.entry_count,
|
|
298
|
+
signature: row.signature,
|
|
299
|
+
timestamp: row.timestamp,
|
|
300
|
+
}));
|
|
301
|
+
} catch (error) {
|
|
302
|
+
console.error('Error getting jackpot wins by wallet:', error);
|
|
303
|
+
return [];
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
async getStats() {
|
|
308
|
+
if (!this._shouldRun()) return null;
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
const result = await this.pool.query(`
|
|
312
|
+
SELECT
|
|
313
|
+
COUNT(*) as total_rounds,
|
|
314
|
+
SUM(CAST(total_pot AS BIGINT)) as total_volume,
|
|
315
|
+
SUM(CAST(win_amount AS BIGINT)) as total_winnings,
|
|
316
|
+
SUM(CAST(total_pot AS BIGINT) - CAST(win_amount AS BIGINT)) as total_fees
|
|
317
|
+
FROM jackpot_rounds
|
|
318
|
+
`);
|
|
319
|
+
|
|
320
|
+
return result.rows[0];
|
|
321
|
+
} catch (error) {
|
|
322
|
+
console.error('Error getting stats:', error);
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Export both class and singleton instance for shared state
|
|
329
|
+
const jackpotHistoryInstance = new JackpotHistory();
|
|
330
|
+
module.exports = JackpotHistory;
|
|
331
|
+
module.exports.instance = jackpotHistoryInstance;
|