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
package/README.md
ADDED
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
# 🎮 Dubs API Server
|
|
2
|
+
|
|
3
|
+
Production-ready REST API for Solana wager games with operator fees, multi-game support, and clean architecture.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Quick Links
|
|
8
|
+
|
|
9
|
+
- **Live Devnet API**: https://dubs-server-dev-55d1fba09a97.herokuapp.com
|
|
10
|
+
- **Program ID**: `8DJTkgk6MDr6tPtw4v2VzYAz9WWvmCg6786vZrEK3o5q`
|
|
11
|
+
- **Solana Explorer**: https://explorer.solana.com/address/8DJTkgk6MDr6tPtw4v2VzYAz9WWvmCg6786vZrEK3o5q?cluster=devnet
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Environments
|
|
16
|
+
|
|
17
|
+
### Local Development (Localnet)
|
|
18
|
+
```bash
|
|
19
|
+
# Start local validator
|
|
20
|
+
solana-test-validator --reset
|
|
21
|
+
|
|
22
|
+
# Deploy program
|
|
23
|
+
cd ../dubs
|
|
24
|
+
solana program deploy target/deploy/hello_world.so --url localhost
|
|
25
|
+
|
|
26
|
+
# Start server
|
|
27
|
+
cd ../dubs-server
|
|
28
|
+
node server.js
|
|
29
|
+
|
|
30
|
+
# API: http://localhost:3001
|
|
31
|
+
# Network: Localnet (your computer)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Devnet Testing (Public Test Network)
|
|
35
|
+
```bash
|
|
36
|
+
# Server already deployed to Heroku!
|
|
37
|
+
# API: https://dubs-server-dev-55d1fba09a97.herokuapp.com
|
|
38
|
+
# Network: Devnet (public)
|
|
39
|
+
# SOL: Free from faucet
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Mainnet Production (Future)
|
|
43
|
+
```bash
|
|
44
|
+
# Deploy program to mainnet
|
|
45
|
+
cd ../dubs
|
|
46
|
+
solana program deploy target/deploy/hello_world.so --url mainnet-beta
|
|
47
|
+
|
|
48
|
+
# Deploy server to Heroku
|
|
49
|
+
heroku apps:create dubs-api-prod --team dubs
|
|
50
|
+
heroku config:set SOLANA_NETWORK=https://api.mainnet-beta.solana.com -a dubs-api-prod
|
|
51
|
+
git push heroku-prod main
|
|
52
|
+
|
|
53
|
+
# API: https://dubs-api-prod.herokuapp.com
|
|
54
|
+
# Network: Mainnet (real $$$)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## API Structure
|
|
60
|
+
|
|
61
|
+
### Production Endpoints (`/api/v1/prod`)
|
|
62
|
+
**For real users with Phantom/Solflare/Jelli wallets**
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
GET /api/v1/prod/game/:gameId
|
|
66
|
+
POST /api/v1/prod/transaction/build/create
|
|
67
|
+
POST /api/v1/prod/transaction/build/join
|
|
68
|
+
POST /api/v1/prod/transaction/build/cast-vote 🗳️ NEW!
|
|
69
|
+
POST /api/v1/prod/transaction/build/distribute-by-vote 🗳️ NEW!
|
|
70
|
+
POST /api/v1/prod/transaction/build/distribute
|
|
71
|
+
POST /api/v1/prod/transaction/submit
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Demo Endpoints (`/api/v1/demo`)
|
|
75
|
+
**For testing with server-managed wallets (local only)**
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
GET /api/v1/demo/game/:gameId
|
|
79
|
+
GET /api/v1/demo/wallets
|
|
80
|
+
POST /api/v1/demo/game/create
|
|
81
|
+
POST /api/v1/demo/game/join
|
|
82
|
+
POST /api/v1/demo/game/distribute
|
|
83
|
+
POST /api/v1/demo/vote/cast 🗳️ NEW!
|
|
84
|
+
POST /api/v1/demo/vote/distribute 🗳️ NEW!
|
|
85
|
+
POST /api/v1/demo/airdrop
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Using Production API (Real Wallets)
|
|
91
|
+
|
|
92
|
+
### 1. Build Create Game Transaction
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
curl -X POST https://dubs-server-dev-55d1fba09a97.herokuapp.com/api/v1/prod/transaction/build/create \
|
|
96
|
+
-H "Content-Type: application/json" \
|
|
97
|
+
-d '{
|
|
98
|
+
"creatorAddress": "YOUR_PHANTOM_WALLET_ADDRESS",
|
|
99
|
+
"buyIn": 0.5,
|
|
100
|
+
"maxPlayers": 4,
|
|
101
|
+
"operatorFee": 10,
|
|
102
|
+
"operatorAddress": "OPTIONAL_OPERATOR_WALLET"
|
|
103
|
+
}'
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Response:**
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"success": true,
|
|
110
|
+
"gameId": "a7d4648b-12b8-43db-9029-728496fb0634",
|
|
111
|
+
"transaction": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAIEPTUQYzFd...",
|
|
112
|
+
"gameAddress": "6KSjVmzu9wKnCojhSvgNoojF9z5Pp3qXEygpJN1ft8rp",
|
|
113
|
+
"instructions": "Sign this transaction with your wallet..."
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 2. Sign Transaction with Phantom
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
import { Connection, Transaction } from '@solana/web3.js';
|
|
121
|
+
|
|
122
|
+
// Get unsigned transaction from API response
|
|
123
|
+
const unsignedTxBase64 = response.transaction;
|
|
124
|
+
|
|
125
|
+
// Decode transaction
|
|
126
|
+
const txBuffer = Buffer.from(unsignedTxBase64, 'base64');
|
|
127
|
+
const tx = Transaction.from(txBuffer);
|
|
128
|
+
|
|
129
|
+
// Sign with Phantom
|
|
130
|
+
const signedTx = await window.solana.signTransaction(tx);
|
|
131
|
+
|
|
132
|
+
// Serialize signed transaction
|
|
133
|
+
const signedTxBase64 = signedTx.serialize().toString('base64');
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 3. Submit Signed Transaction
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
curl -X POST https://dubs-server-dev-55d1fba09a97.herokuapp.com/api/v1/prod/transaction/submit \
|
|
140
|
+
-H "Content-Type: application/json" \
|
|
141
|
+
-d '{
|
|
142
|
+
"signedTransaction": "SIGNED_TX_BASE64_HERE"
|
|
143
|
+
}'
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Response:**
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"success": true,
|
|
150
|
+
"transaction": "5m9hH7e2Dc59Y4dVuXsXJCJVbpq8gh2NFGHo6HT5cBMGL4aYPUW2rCcTZuLR2ETY71LXkZGjJBsDh5qzsfUuLMCi",
|
|
151
|
+
"message": "Transaction confirmed on blockchain"
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### 4. View on Solana Explorer
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
https://explorer.solana.com/tx/YOUR_TX_SIGNATURE?cluster=devnet
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Complete Client Integration Example
|
|
164
|
+
|
|
165
|
+
### React/Next.js with Phantom
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import { useWallet } from '@solana/wallet-adapter-react';
|
|
169
|
+
import { Connection, Transaction } from '@solana/web3.js';
|
|
170
|
+
|
|
171
|
+
const API_BASE = 'https://dubs-server-dev-55d1fba09a97.herokuapp.com';
|
|
172
|
+
|
|
173
|
+
async function createGame() {
|
|
174
|
+
const { publicKey, signTransaction } = useWallet();
|
|
175
|
+
|
|
176
|
+
// Step 1: Build unsigned transaction
|
|
177
|
+
const buildRes = await fetch(`${API_BASE}/api/v1/prod/transaction/build/create`, {
|
|
178
|
+
method: 'POST',
|
|
179
|
+
headers: { 'Content-Type': 'application/json' },
|
|
180
|
+
body: JSON.stringify({
|
|
181
|
+
creatorAddress: publicKey.toString(),
|
|
182
|
+
buyIn: 0.5,
|
|
183
|
+
maxPlayers: 4,
|
|
184
|
+
operatorFee: 10,
|
|
185
|
+
}),
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const { transaction: unsignedTx, gameId } = await buildRes.json();
|
|
189
|
+
|
|
190
|
+
// Step 2: Decode and sign
|
|
191
|
+
const txBuffer = Buffer.from(unsignedTx, 'base64');
|
|
192
|
+
const tx = Transaction.from(txBuffer);
|
|
193
|
+
const signedTx = await signTransaction(tx);
|
|
194
|
+
|
|
195
|
+
// Step 3: Submit signed transaction
|
|
196
|
+
const submitRes = await fetch(`${API_BASE}/api/v1/prod/transaction/submit`, {
|
|
197
|
+
method: 'POST',
|
|
198
|
+
headers: { 'Content-Type': 'application/json' },
|
|
199
|
+
body: JSON.stringify({
|
|
200
|
+
signedTransaction: signedTx.serialize().toString('base64'),
|
|
201
|
+
}),
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const result = await submitRes.json();
|
|
205
|
+
console.log('Game created!', { gameId, tx: result.transaction });
|
|
206
|
+
|
|
207
|
+
return gameId;
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Join Game
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
async function joinGame(gameId: string) {
|
|
215
|
+
const { publicKey, signTransaction } = useWallet();
|
|
216
|
+
|
|
217
|
+
// Build unsigned transaction
|
|
218
|
+
const buildRes = await fetch(`${API_BASE}/api/v1/prod/transaction/build/join`, {
|
|
219
|
+
method: 'POST',
|
|
220
|
+
headers: { 'Content-Type': 'application/json' },
|
|
221
|
+
body: JSON.stringify({
|
|
222
|
+
playerAddress: publicKey.toString(),
|
|
223
|
+
gameId,
|
|
224
|
+
}),
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const { transaction } = await buildRes.json();
|
|
228
|
+
|
|
229
|
+
// Sign and submit
|
|
230
|
+
const txBuffer = Buffer.from(transaction, 'base64');
|
|
231
|
+
const tx = Transaction.from(txBuffer);
|
|
232
|
+
const signedTx = await signTransaction(tx);
|
|
233
|
+
|
|
234
|
+
const submitRes = await fetch(`${API_BASE}/api/v1/prod/transaction/submit`, {
|
|
235
|
+
method: 'POST',
|
|
236
|
+
headers: { 'Content-Type': 'application/json' },
|
|
237
|
+
body: JSON.stringify({
|
|
238
|
+
signedTransaction: signedTx.serialize().toString('base64'),
|
|
239
|
+
}),
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
return await submitRes.json();
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### View Game
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
async function getGameInfo(gameId: string) {
|
|
250
|
+
const res = await fetch(`${API_BASE}/api/v1/prod/game/${gameId}`);
|
|
251
|
+
return await res.json();
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Postman Testing
|
|
258
|
+
|
|
259
|
+
**Import:** `postman/Dubs-API-v1.postman_collection.json`
|
|
260
|
+
|
|
261
|
+
**Update Variables:**
|
|
262
|
+
- `baseUrl`: `https://dubs-server-dev-55d1fba09a97.herokuapp.com` (for devnet)
|
|
263
|
+
- `gameId`: Auto-saved after creating game
|
|
264
|
+
|
|
265
|
+
**Test Flow:**
|
|
266
|
+
1. Production API → Build Create Game Transaction
|
|
267
|
+
2. (Sign with Phantom - do this manually or in your app)
|
|
268
|
+
3. Production API → Submit Signed Transaction
|
|
269
|
+
4. Production API → Get Game Info
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Environment Variables
|
|
274
|
+
|
|
275
|
+
### Required:
|
|
276
|
+
```bash
|
|
277
|
+
SOLANA_NETWORK=https://api.devnet.solana.com # or mainnet-beta
|
|
278
|
+
PROGRAM_ID=8DJTkgk6MDr6tPtw4v2VzYAz9WWvmCg6786vZrEK3o5q
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Optional:
|
|
282
|
+
```bash
|
|
283
|
+
PORT=3001 # Heroku sets this automatically
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Set on Heroku:
|
|
287
|
+
```bash
|
|
288
|
+
heroku config:set SOLANA_NETWORK=https://api.devnet.solana.com -a dubs-server-dev
|
|
289
|
+
heroku config:set PROGRAM_ID=8DJTkgk6MDr6tPtw4v2VzYAz9WWvmCg6786vZrEK3o5q -a dubs-server-dev
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Deployment
|
|
295
|
+
|
|
296
|
+
### Devnet (Current)
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
# Already deployed!
|
|
300
|
+
# URL: https://dubs-server-dev-55d1fba09a97.herokuapp.com
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
To redeploy:
|
|
304
|
+
```bash
|
|
305
|
+
git add .
|
|
306
|
+
git commit -m "Update"
|
|
307
|
+
git push heroku-dev main
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Mainnet (Future)
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
# 1. Deploy Solana program to mainnet
|
|
314
|
+
cd ../dubs
|
|
315
|
+
solana program deploy target/deploy/hello_world.so --url mainnet-beta
|
|
316
|
+
|
|
317
|
+
# 2. Create Heroku app for mainnet
|
|
318
|
+
heroku apps:create dubs-api-prod --team dubs
|
|
319
|
+
|
|
320
|
+
# 3. Add remote
|
|
321
|
+
git remote add heroku-prod https://git.heroku.com/dubs-api-prod.git
|
|
322
|
+
|
|
323
|
+
# 4. Configure for mainnet
|
|
324
|
+
heroku config:set SOLANA_NETWORK=https://api.mainnet-beta.solana.com -a dubs-api-prod
|
|
325
|
+
heroku config:set PROGRAM_ID=8DJTkgk6MDr6tPtw4v2VzYAz9WWvmCg6786vZrEK3o5q -a dubs-api-prod
|
|
326
|
+
|
|
327
|
+
# 5. Deploy
|
|
328
|
+
git push heroku-prod main
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## Features
|
|
334
|
+
|
|
335
|
+
✅ **UUID Game IDs** - Professional, unique identifiers
|
|
336
|
+
✅ **Address-Based Winners** - No confusing indices
|
|
337
|
+
✅ **Multi-Game Support** - Unlimited simultaneous games
|
|
338
|
+
✅ **Operator Fees** - Built-in monetization (0-100%)
|
|
339
|
+
✅ **Multi-Winner Payouts** - Equal or custom splits
|
|
340
|
+
✅ **3 Game Modes** - Manual, Democratic, Referee ⚖️ (NEW!)
|
|
341
|
+
✅ **Democratic Voting** - 🗳️ Players vote for winners
|
|
342
|
+
✅ **Majority Rules** - 🗳️ 50%+ players decide outcome
|
|
343
|
+
✅ **Referee System** - ⚖️ Expert judges earn commission (NEW!)
|
|
344
|
+
✅ **Trustless Distribution** - Anyone can trigger when ready
|
|
345
|
+
✅ **Clean API** - Versioned (`/api/v1/`)
|
|
346
|
+
✅ **Dual Mode** - Production & Demo endpoints
|
|
347
|
+
✅ **Heroku Ready** - One-command deploy
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## API Endpoints Summary
|
|
352
|
+
|
|
353
|
+
### Production (Real Wallets):
|
|
354
|
+
- Build unsigned transactions
|
|
355
|
+
- Client signs with wallet
|
|
356
|
+
- Submit to blockchain
|
|
357
|
+
|
|
358
|
+
### Demo (Server-Managed):
|
|
359
|
+
- Server creates & signs
|
|
360
|
+
- Easy testing
|
|
361
|
+
- Local development only
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Tech Stack
|
|
366
|
+
|
|
367
|
+
- **Node.js**: 20.x
|
|
368
|
+
- **Express**: 4.18.2
|
|
369
|
+
- **@solana/web3.js**: 1.95.8
|
|
370
|
+
- **Solana Program**: Anchor 0.29.0, Rust 1.88.0
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## 🗳️ Democratic Voting System (NEW!)
|
|
375
|
+
|
|
376
|
+
### Overview
|
|
377
|
+
|
|
378
|
+
Games can now be created with **democratic voting** enabled! Players vote for winners, and the smart contract automatically tallies votes and distributes prizes based on majority rules.
|
|
379
|
+
|
|
380
|
+
### How It Works
|
|
381
|
+
|
|
382
|
+
1. **Create Game with Voting:**
|
|
383
|
+
```json
|
|
384
|
+
{
|
|
385
|
+
"creatorAddress": "...",
|
|
386
|
+
"buyIn": 0.5,
|
|
387
|
+
"maxPlayers": 4,
|
|
388
|
+
"votingEnabled": true ← Enable voting!
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
2. **Players Join:**
|
|
393
|
+
- Standard join flow
|
|
394
|
+
- All players can vote
|
|
395
|
+
|
|
396
|
+
3. **Players Vote:**
|
|
397
|
+
```json
|
|
398
|
+
POST /api/v1/prod/transaction/build/cast-vote
|
|
399
|
+
{
|
|
400
|
+
"voterAddress": "PlayerAddress",
|
|
401
|
+
"gameId": "uuid",
|
|
402
|
+
"votedFor": "AnotherPlayerAddress"
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
4. **Check Voting Progress:**
|
|
407
|
+
```json
|
|
408
|
+
GET /api/v1/prod/game/:gameId
|
|
409
|
+
|
|
410
|
+
Response includes:
|
|
411
|
+
{
|
|
412
|
+
"votes": [
|
|
413
|
+
{"voter": "Player1", "votedFor": "Player2"},
|
|
414
|
+
{"voter": "Player2", "votedFor": "Player2"}
|
|
415
|
+
],
|
|
416
|
+
"votingEnabled": true
|
|
417
|
+
}
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
5. **Distribute by Vote (When Majority Reached):**
|
|
421
|
+
```json
|
|
422
|
+
POST /api/v1/prod/transaction/build/distribute-by-vote
|
|
423
|
+
{
|
|
424
|
+
"creatorAddress": "...",
|
|
425
|
+
"gameId": "uuid"
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Majority Rules
|
|
430
|
+
|
|
431
|
+
```
|
|
432
|
+
Total Players: 3 → Need 2 votes (majority)
|
|
433
|
+
Total Players: 4 → Need 3 votes (majority)
|
|
434
|
+
Total Players: 2 → Need 2 votes (both)
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
**Formula:** `(total_players / 2) + 1`
|
|
438
|
+
|
|
439
|
+
### Tie Handling
|
|
440
|
+
|
|
441
|
+
If multiple players tied for most votes:
|
|
442
|
+
- Prize split equally among tied winners
|
|
443
|
+
- Example: 2-way tie → 50/50 split
|
|
444
|
+
|
|
445
|
+
### Vote Changes
|
|
446
|
+
|
|
447
|
+
- ✅ Players can change votes before majority
|
|
448
|
+
- ✅ Latest vote overwrites previous vote
|
|
449
|
+
- ✅ All votes stored on-chain
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## What's Next
|
|
454
|
+
|
|
455
|
+
### Phase 6: Advanced Voting Features
|
|
456
|
+
|
|
457
|
+
- Time-based voting deadlines
|
|
458
|
+
- Weighted voting (based on buy-in multiples)
|
|
459
|
+
- Anonymous voting
|
|
460
|
+
- Vote delegation
|
|
461
|
+
|
|
462
|
+
---
|
|
463
|
+
|
|
464
|
+
## Support
|
|
465
|
+
|
|
466
|
+
- **Documentation**: See `DUBS-PROJECT.md` in parent directory
|
|
467
|
+
- **Postman Collection**: Import `postman/Dubs-API-v1-With-Voting.postman_collection.json`
|
|
468
|
+
- **Voting Guide**: See `postman/VOTING_API_GUIDE.md`
|
|
469
|
+
- **Referee Mode**: See `REFEREE_MODE_GUIDE.md` ⚖️ (NEW!)
|
|
470
|
+
- **CLI Tool**: Run `npm run cli` for interactive testing
|
|
471
|
+
- **Issues**: Check Heroku logs with `heroku logs --tail -a dubs-server-dev`
|
|
472
|
+
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
**Built with ❤️ on Solana**
|
|
476
|
+
|