-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
164 lines (132 loc) · 4.99 KB
/
main.go
File metadata and controls
164 lines (132 loc) · 4.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package main
import (
"context"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/gorilla/mux"
_ "github.com/purro-wallet/purro-core/docs"
"github.com/purro-wallet/purro-core/src/config"
handler "github.com/purro-wallet/purro-core/src/handlers"
"github.com/purro-wallet/purro-core/src/infrastructure/api"
"github.com/purro-wallet/purro-core/src/infrastructure/database"
service "github.com/purro-wallet/purro-core/src/services"
httpSwagger "github.com/swaggo/http-swagger"
)
// @title Purro Trading Aggregator API
// @version 1.0
// @description API for trading leaderboard, blockchain synchronization, and trader analytics
// @termsOfService http://swagger.io/terms/
// @contact.name Purro Wallet Team
// @host
// @BasePath /
func main() {
// Load configuration from file
cfg, err := config.LoadConfig("")
if err != nil {
log.Fatalf("Failed to load config: %v", err)
}
// Initialize database with config
if err := database.InitDatabase(cfg.Database); err != nil {
log.Fatalf("Failed to initialize database: %v", err)
}
defer database.CloseDatabase()
log.Println("✅ GORM database initialized successfully!")
log.Println("✅ Setting up services and handlers...")
// Create external APIs
etherscanAPIKeys := os.Getenv("ETHERSCAN_API_KEYS")
if etherscanAPIKeys == "" {
log.Fatalf("ETHERSCAN_API_KEYS environment variable is required")
}
etherscanAPI := api.NewEtherscanAPI(etherscanAPIKeys)
// Create services
newAggregatorSyncService := service.NewNewAggregatorSyncService(etherscanAPI)
databaseLeaderboardService := service.NewDatabaseLeaderboardService()
statsService := service.NewStatsService()
// Create WebSocket service
wsService := service.NewWebSocketService()
// Create trading bot service
encryptionKey := cfg.Blockchain.EncryptionKey
tradingBotService := service.NewTradingBotService(encryptionKey, wsService, cfg)
// Create bot swap service
botSwapService := service.NewBotSwapService(tradingBotService, wsService, cfg, database.DB)
// Create handlers
syncHandler := handler.NewSyncHandler(newAggregatorSyncService)
leaderboardHandler := handler.NewLeaderboardHandler(databaseLeaderboardService)
statsHandler := handler.NewStatsHandler(statsService)
tradingBotHandler := handler.NewTradingBotHandler(tradingBotService, wsService, botSwapService)
// Create router
r := mux.NewRouter()
// Create API v1 subrouter with /api/v1 prefix
apiV1 := r.PathPrefix("/api/v1").Subrouter()
// Register routes to API v1 subrouter
syncHandler.RegisterRoutes(apiV1)
leaderboardHandler.RegisterRoutes(apiV1)
statsHandler.RegisterRoutes(apiV1)
tradingBotHandler.RegisterRoutes(apiV1)
// Also register routes to root for backward compatibility
syncHandler.RegisterRoutes(r)
// Add swagger endpoint
r.PathPrefix("/swagger/").Handler(httpSwagger.WrapHandler)
// Health check
r.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
})
// Create a router with middleware
routerWithMiddleware := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
// Add CORS headers
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
// Handle preflight requests
if req.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
// Continue with the request
r.ServeHTTP(w, req)
})
// Create server
server := &http.Server{
Addr: ":8080",
Handler: routerWithMiddleware, // Use the router with middleware
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
IdleTimeout: 60 * time.Second,
}
log.Printf("GORM Models ready. Database tables created successfully!")
// Start server in a goroutine
go func() {
log.Printf("🚀 Server starting on port 8080...")
log.Printf("📊 Available endpoints:")
log.Printf(" POST /sync - Blockchain sync API")
log.Printf(" GET /sync/status - Sync status")
log.Printf(" GET /leaderboard - Trading leaderboard")
log.Printf(" GET /leaderboard/trader/{address} - Trader details")
log.Printf(" GET /stats - Platform statistics")
log.Printf(" 🤖 Trading Bot API:")
log.Printf(" GET /ws - WebSocket for real-time updates")
log.Printf(" POST /execute-random-session - Automated bot trading session")
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("Failed to start server: %v", err)
}
}()
// Set up channel to listen for signals
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
// Block until signal is received
<-stop
// Create a deadline for server shutdown
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
// Shutdown server gracefully
log.Println("Shutting down server...")
if err := server.Shutdown(ctx); err != nil {
log.Fatalf("Server shutdown failed: %v", err)
}
log.Println("Server stopped")
}