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,392 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 💰 Referral Earnings API Routes
|
|
3
|
+
*
|
|
4
|
+
* Endpoints for viewing and managing referral commissions.
|
|
5
|
+
* Referrers earn 1% of their referees' buy-ins.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const express = require('express');
|
|
9
|
+
const router = express.Router();
|
|
10
|
+
const { authenticate } = require('../middleware/authenticate');
|
|
11
|
+
const referralEarningsService = require('../services/referralEarningsService');
|
|
12
|
+
|
|
13
|
+
module.exports = () => {
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* GET /api/referral-earnings/me
|
|
17
|
+
* Get authenticated user's referral earnings
|
|
18
|
+
* Requires authentication
|
|
19
|
+
*/
|
|
20
|
+
router.get('/me', authenticate, async (req, res) => {
|
|
21
|
+
try {
|
|
22
|
+
const walletAddress = req.user.walletAddress;
|
|
23
|
+
const { limit = 50, offset = 0, status } = req.query;
|
|
24
|
+
|
|
25
|
+
console.log(`[ReferralEarnings API] Getting earnings for ${walletAddress.slice(0, 8)}...`);
|
|
26
|
+
|
|
27
|
+
const result = await referralEarningsService.getEarningsForWallet(walletAddress, {
|
|
28
|
+
limit: parseInt(limit),
|
|
29
|
+
offset: parseInt(offset),
|
|
30
|
+
status: status || null
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
res.json({
|
|
34
|
+
success: true,
|
|
35
|
+
...result
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error('[ReferralEarnings API] Error getting earnings:', error.message);
|
|
40
|
+
res.status(500).json({
|
|
41
|
+
success: false,
|
|
42
|
+
error: error.message
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* GET /api/referral-earnings/me/summary
|
|
49
|
+
* Get quick summary for authenticated user (for dashboard widgets)
|
|
50
|
+
* Requires authentication
|
|
51
|
+
*/
|
|
52
|
+
router.get('/me/summary', authenticate, async (req, res) => {
|
|
53
|
+
try {
|
|
54
|
+
const walletAddress = req.user.walletAddress;
|
|
55
|
+
|
|
56
|
+
const result = await referralEarningsService.getEarningsForWallet(walletAddress, {
|
|
57
|
+
limit: 1,
|
|
58
|
+
offset: 0
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
res.json({
|
|
62
|
+
success: true,
|
|
63
|
+
summary: result.summary
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error('[ReferralEarnings API] Error getting summary:', error.message);
|
|
68
|
+
res.status(500).json({
|
|
69
|
+
success: false,
|
|
70
|
+
error: error.message
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* GET /api/referral-earnings/me/recent
|
|
77
|
+
* Get recent earnings for authenticated user (last 10)
|
|
78
|
+
* Requires authentication
|
|
79
|
+
*/
|
|
80
|
+
router.get('/me/recent', authenticate, async (req, res) => {
|
|
81
|
+
try {
|
|
82
|
+
const walletAddress = req.user.walletAddress;
|
|
83
|
+
|
|
84
|
+
const result = await referralEarningsService.getEarningsForWallet(walletAddress, {
|
|
85
|
+
limit: 10,
|
|
86
|
+
offset: 0
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
res.json({
|
|
90
|
+
success: true,
|
|
91
|
+
recentEarnings: result.earnings
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.error('[ReferralEarnings API] Error getting recent earnings:', error.message);
|
|
96
|
+
res.status(500).json({
|
|
97
|
+
success: false,
|
|
98
|
+
error: error.message
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* GET /api/referral-earnings/leaderboard
|
|
105
|
+
* Get referral earnings leaderboard (public)
|
|
106
|
+
*/
|
|
107
|
+
router.get('/leaderboard', async (req, res) => {
|
|
108
|
+
try {
|
|
109
|
+
const { limit = 20 } = req.query;
|
|
110
|
+
|
|
111
|
+
const leaderboard = await referralEarningsService.getLeaderboard(parseInt(limit));
|
|
112
|
+
|
|
113
|
+
res.json({
|
|
114
|
+
success: true,
|
|
115
|
+
leaderboard
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.error('[ReferralEarnings API] Error getting leaderboard:', error.message);
|
|
120
|
+
res.status(500).json({
|
|
121
|
+
success: false,
|
|
122
|
+
error: error.message
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* GET /api/referral-earnings/stats
|
|
129
|
+
* Get platform-wide referral stats (public)
|
|
130
|
+
*/
|
|
131
|
+
router.get('/stats', async (req, res) => {
|
|
132
|
+
try {
|
|
133
|
+
const stats = await referralEarningsService.getPlatformStats();
|
|
134
|
+
|
|
135
|
+
res.json({
|
|
136
|
+
success: true,
|
|
137
|
+
stats
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error('[ReferralEarnings API] Error getting platform stats:', error.message);
|
|
142
|
+
res.status(500).json({
|
|
143
|
+
success: false,
|
|
144
|
+
error: error.message
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* GET /api/referral-earnings/user/:walletAddress
|
|
151
|
+
* Get public referral stats for any user
|
|
152
|
+
* Returns only summary (no detailed earnings)
|
|
153
|
+
*/
|
|
154
|
+
router.get('/user/:walletAddress', async (req, res) => {
|
|
155
|
+
try {
|
|
156
|
+
const { walletAddress } = req.params;
|
|
157
|
+
|
|
158
|
+
const result = await referralEarningsService.getEarningsForWallet(walletAddress, {
|
|
159
|
+
limit: 0, // Don't fetch individual earnings
|
|
160
|
+
offset: 0
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
res.json({
|
|
164
|
+
success: true,
|
|
165
|
+
walletAddress,
|
|
166
|
+
summary: {
|
|
167
|
+
totalEarnedSOL: result.summary.totalEarnedSOL,
|
|
168
|
+
uniqueReferees: result.summary.uniqueReferees,
|
|
169
|
+
gamesCount: result.summary.gamesCount
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
} catch (error) {
|
|
174
|
+
console.error('[ReferralEarnings API] Error getting user stats:', error.message);
|
|
175
|
+
res.status(500).json({
|
|
176
|
+
success: false,
|
|
177
|
+
error: error.message
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* GET /api/referral-earnings/wallet/:walletAddress
|
|
184
|
+
* Get referral earnings with transaction signatures for transaction history linking
|
|
185
|
+
* Used by frontend GameLinkingService
|
|
186
|
+
*/
|
|
187
|
+
router.get('/wallet/:walletAddress', async (req, res) => {
|
|
188
|
+
try {
|
|
189
|
+
const { walletAddress } = req.params;
|
|
190
|
+
|
|
191
|
+
const result = await referralEarningsService.getEarningsForWallet(walletAddress, {
|
|
192
|
+
limit: 100, // Get recent earnings for transaction matching
|
|
193
|
+
offset: 0
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
res.json({
|
|
197
|
+
success: true,
|
|
198
|
+
earnings: result.earnings
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.error('[ReferralEarnings API] Error getting wallet earnings:', error.message);
|
|
203
|
+
res.status(500).json({
|
|
204
|
+
success: false,
|
|
205
|
+
error: error.message
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* POST /api/referral-earnings/process-game
|
|
212
|
+
* Process referral commissions for a resolved game
|
|
213
|
+
* Called by the oracle after game resolution
|
|
214
|
+
*
|
|
215
|
+
* Note: This can be secured with API key or made internal-only
|
|
216
|
+
*/
|
|
217
|
+
router.post('/process-game', async (req, res) => {
|
|
218
|
+
try {
|
|
219
|
+
const { gameId, gameType, potSizeLamports } = req.body;
|
|
220
|
+
|
|
221
|
+
// Validate required fields
|
|
222
|
+
if (!gameId || !gameType || !potSizeLamports) {
|
|
223
|
+
return res.status(400).json({
|
|
224
|
+
success: false,
|
|
225
|
+
error: 'Missing required fields: gameId, gameType, potSizeLamports'
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
console.log(`[ReferralEarnings API] Processing commissions for game ${gameId}`);
|
|
230
|
+
|
|
231
|
+
const result = await referralEarningsService.processGameCommissions(
|
|
232
|
+
gameId,
|
|
233
|
+
gameType,
|
|
234
|
+
parseInt(potSizeLamports)
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
res.json({
|
|
238
|
+
success: true,
|
|
239
|
+
message: `Processed ${result.commissions.length} referral commissions`,
|
|
240
|
+
summary: result
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
} catch (error) {
|
|
244
|
+
console.error('[ReferralEarnings API] Error processing game:', error.message);
|
|
245
|
+
res.status(500).json({
|
|
246
|
+
success: false,
|
|
247
|
+
error: error.message
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* GET /api/referral-earnings/pending-payouts
|
|
254
|
+
* Get all pending payouts grouped by referrer (admin/operator only)
|
|
255
|
+
* For batch payout processing
|
|
256
|
+
*/
|
|
257
|
+
router.get('/pending-payouts', async (req, res) => {
|
|
258
|
+
try {
|
|
259
|
+
const { minAmount = 0 } = req.query;
|
|
260
|
+
|
|
261
|
+
const pendingPayouts = await referralEarningsService.getPendingPayouts(parseInt(minAmount));
|
|
262
|
+
|
|
263
|
+
// Calculate totals
|
|
264
|
+
const totalPending = pendingPayouts.reduce((sum, p) => sum + p.totalPendingLamports, 0);
|
|
265
|
+
|
|
266
|
+
res.json({
|
|
267
|
+
success: true,
|
|
268
|
+
totalReferrers: pendingPayouts.length,
|
|
269
|
+
totalPendingLamports: totalPending,
|
|
270
|
+
totalPendingSOL: totalPending / referralEarningsService.LAMPORTS_PER_SOL,
|
|
271
|
+
payouts: pendingPayouts
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
} catch (error) {
|
|
275
|
+
console.error('[ReferralEarnings API] Error getting pending payouts:', error.message);
|
|
276
|
+
res.status(500).json({
|
|
277
|
+
success: false,
|
|
278
|
+
error: error.message
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* POST /api/referral-earnings/mark-paid
|
|
285
|
+
* Mark earnings as paid after successful payout transaction
|
|
286
|
+
* Called by the payout script/cron
|
|
287
|
+
*/
|
|
288
|
+
router.post('/mark-paid', async (req, res) => {
|
|
289
|
+
try {
|
|
290
|
+
const { referrerWallet, txSignature, batchId } = req.body;
|
|
291
|
+
|
|
292
|
+
if (!referrerWallet || !txSignature) {
|
|
293
|
+
return res.status(400).json({
|
|
294
|
+
success: false,
|
|
295
|
+
error: 'Missing required fields: referrerWallet, txSignature'
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const count = await referralEarningsService.markEarningsAsPaid(
|
|
300
|
+
referrerWallet,
|
|
301
|
+
txSignature,
|
|
302
|
+
batchId || null
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
res.json({
|
|
306
|
+
success: true,
|
|
307
|
+
message: `Marked ${count} earnings as paid`,
|
|
308
|
+
recordsUpdated: count
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
} catch (error) {
|
|
312
|
+
console.error('[ReferralEarnings API] Error marking as paid:', error.message);
|
|
313
|
+
res.status(500).json({
|
|
314
|
+
success: false,
|
|
315
|
+
error: error.message
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* POST /api/referral-earnings/record
|
|
322
|
+
* Record an on-chain referral commission payment
|
|
323
|
+
* Called by the oracle after game resolution with referrer
|
|
324
|
+
*
|
|
325
|
+
* This is for tracking/display purposes - the actual SOL transfer
|
|
326
|
+
* happens on-chain during game resolution.
|
|
327
|
+
*/
|
|
328
|
+
router.post('/record', async (req, res) => {
|
|
329
|
+
const { gameId, referrerWallet, commissionLamports, paidOnChain, txSignature, gameType } = req.body;
|
|
330
|
+
const logPrefix = `[RECORD-COMMISSION:${gameId?.slice(-8) || 'unknown'}]`;
|
|
331
|
+
|
|
332
|
+
console.log(`${logPrefix} 📝 Incoming request to record on-chain commission`);
|
|
333
|
+
console.log(`${logPrefix} Request body: ${JSON.stringify(req.body)}`);
|
|
334
|
+
|
|
335
|
+
try {
|
|
336
|
+
if (!gameId || !referrerWallet || commissionLamports === undefined) {
|
|
337
|
+
console.log(`${logPrefix} ❌ Missing required fields`);
|
|
338
|
+
console.log(`${logPrefix} gameId: ${gameId || 'MISSING'}`);
|
|
339
|
+
console.log(`${logPrefix} referrerWallet: ${referrerWallet || 'MISSING'}`);
|
|
340
|
+
console.log(`${logPrefix} commissionLamports: ${commissionLamports === undefined ? 'MISSING' : commissionLamports}`);
|
|
341
|
+
return res.status(400).json({
|
|
342
|
+
success: false,
|
|
343
|
+
error: 'Missing required fields: gameId, referrerWallet, commissionLamports'
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
console.log(`${logPrefix} ✅ All required fields present`);
|
|
348
|
+
console.log(`${logPrefix} Game ID: ${gameId}`);
|
|
349
|
+
console.log(`${logPrefix} Referrer: ${referrerWallet}`);
|
|
350
|
+
console.log(`${logPrefix} Commission: ${commissionLamports} lamports (${commissionLamports / 1_000_000_000} SOL)`);
|
|
351
|
+
console.log(`${logPrefix} Paid on-chain: ${paidOnChain}`);
|
|
352
|
+
console.log(`${logPrefix} TX Signature: ${txSignature || 'NOT PROVIDED'}`);
|
|
353
|
+
console.log(`${logPrefix} Game type: ${gameType || 'sports (default)'}`);
|
|
354
|
+
|
|
355
|
+
if (!txSignature) {
|
|
356
|
+
console.log(`${logPrefix} ⚠️ WARNING: No transaction signature provided - this record cannot be verified on-chain!`);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Record in database for tracking
|
|
360
|
+
console.log(`${logPrefix} Calling recordOnChainCommission service...`);
|
|
361
|
+
const result = await referralEarningsService.recordOnChainCommission(
|
|
362
|
+
gameId,
|
|
363
|
+
referrerWallet,
|
|
364
|
+
parseInt(commissionLamports),
|
|
365
|
+
paidOnChain === true,
|
|
366
|
+
txSignature || null,
|
|
367
|
+
gameType || 'sports' // Default to sports for backwards compatibility
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
console.log(`${logPrefix} ✅ Service call completed`);
|
|
371
|
+
console.log(`${logPrefix} Result: ${JSON.stringify(result)}`);
|
|
372
|
+
|
|
373
|
+
res.json({
|
|
374
|
+
success: true,
|
|
375
|
+
message: `Recorded ${commissionLamports / 1_000_000_000} SOL commission`,
|
|
376
|
+
...result
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
} catch (error) {
|
|
380
|
+
console.error(`${logPrefix} ❌ ERROR recording commission:`);
|
|
381
|
+
console.error(`${logPrefix} Message: ${error.message}`);
|
|
382
|
+
console.error(`${logPrefix} Stack: ${error.stack}`);
|
|
383
|
+
res.status(500).json({
|
|
384
|
+
success: false,
|
|
385
|
+
error: error.message
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
return router;
|
|
391
|
+
};
|
|
392
|
+
|