Add full monorepo: virtual-banker, backend, frontend, docs, scripts, deployment
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
166
backend/api/rest/routes.go
Normal file
166
backend/api/rest/routes.go
Normal file
@@ -0,0 +1,166 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SetupRoutes sets up all API routes
|
||||
func (s *Server) SetupRoutes(mux *http.ServeMux) {
|
||||
// Block routes
|
||||
mux.HandleFunc("/api/v1/blocks", s.handleListBlocks)
|
||||
mux.HandleFunc("/api/v1/blocks/", s.handleBlockDetail)
|
||||
|
||||
// Transaction routes
|
||||
mux.HandleFunc("/api/v1/transactions", s.handleListTransactions)
|
||||
mux.HandleFunc("/api/v1/transactions/", s.handleTransactionDetail)
|
||||
|
||||
// Address routes
|
||||
mux.HandleFunc("/api/v1/addresses/", s.handleAddressDetail)
|
||||
|
||||
// Search route
|
||||
mux.HandleFunc("/api/v1/search", s.handleSearch)
|
||||
|
||||
// Stats route
|
||||
mux.HandleFunc("/api/v2/stats", s.handleStats)
|
||||
|
||||
// Etherscan-compatible API route
|
||||
mux.HandleFunc("/api", s.handleEtherscanAPI)
|
||||
|
||||
// Health check
|
||||
mux.HandleFunc("/health", s.handleHealth)
|
||||
|
||||
// MetaMask / dual-chain config (Chain 138 + Ethereum Mainnet)
|
||||
mux.HandleFunc("/api/config/networks", s.handleConfigNetworks)
|
||||
mux.HandleFunc("/api/config/token-list", s.handleConfigTokenList)
|
||||
|
||||
// Feature flags endpoint
|
||||
mux.HandleFunc("/api/v1/features", s.handleFeatures)
|
||||
|
||||
// Auth endpoints
|
||||
mux.HandleFunc("/api/v1/auth/nonce", s.handleAuthNonce)
|
||||
mux.HandleFunc("/api/v1/auth/wallet", s.handleAuthWallet)
|
||||
|
||||
// Track 1 routes (public, optional auth)
|
||||
// Note: Track 1 endpoints should be registered with OptionalAuth middleware
|
||||
// mux.HandleFunc("/api/v1/track1/blocks/latest", s.track1Server.handleLatestBlocks)
|
||||
// mux.HandleFunc("/api/v1/track1/txs/latest", s.track1Server.handleLatestTransactions)
|
||||
// mux.HandleFunc("/api/v1/track1/block/", s.track1Server.handleBlockDetail)
|
||||
// mux.HandleFunc("/api/v1/track1/tx/", s.track1Server.handleTransactionDetail)
|
||||
// mux.HandleFunc("/api/v1/track1/address/", s.track1Server.handleAddressBalance)
|
||||
// mux.HandleFunc("/api/v1/track1/bridge/status", s.track1Server.handleBridgeStatus)
|
||||
|
||||
// Track 2 routes (require Track 2+)
|
||||
// Note: Track 2 endpoints should be registered with RequireAuth + RequireTrack(2) middleware
|
||||
// mux.HandleFunc("/api/v1/track2/address/", s.track2Server.handleAddressTransactions)
|
||||
// mux.HandleFunc("/api/v1/track2/token/", s.track2Server.handleTokenInfo)
|
||||
// mux.HandleFunc("/api/v1/track2/search", s.track2Server.handleSearch)
|
||||
|
||||
// Track 3 routes (require Track 3+)
|
||||
// Note: Track 3 endpoints should be registered with RequireAuth + RequireTrack(3) middleware
|
||||
// mux.HandleFunc("/api/v1/track3/analytics/flows", s.track3Server.handleFlows)
|
||||
// mux.HandleFunc("/api/v1/track3/analytics/bridge", s.track3Server.handleBridge)
|
||||
// mux.HandleFunc("/api/v1/track3/analytics/token-distribution/", s.track3Server.handleTokenDistribution)
|
||||
// mux.HandleFunc("/api/v1/track3/analytics/address-risk/", s.track3Server.handleAddressRisk)
|
||||
|
||||
// Track 4 routes (require Track 4)
|
||||
// Note: Track 4 endpoints should be registered with RequireAuth + RequireTrack(4) + IP whitelist middleware
|
||||
// mux.HandleFunc("/api/v1/track4/operator/bridge/events", s.track4Server.handleBridgeEvents)
|
||||
// mux.HandleFunc("/api/v1/track4/operator/validators", s.track4Server.handleValidators)
|
||||
// mux.HandleFunc("/api/v1/track4/operator/contracts", s.track4Server.handleContracts)
|
||||
// mux.HandleFunc("/api/v1/track4/operator/protocol-state", s.track4Server.handleProtocolState)
|
||||
}
|
||||
|
||||
// handleBlockDetail handles GET /api/v1/blocks/{chain_id}/{number} or /api/v1/blocks/{chain_id}/hash/{hash}
|
||||
func (s *Server) handleBlockDetail(w http.ResponseWriter, r *http.Request) {
|
||||
path := strings.TrimPrefix(r.URL.Path, "/api/v1/blocks/")
|
||||
parts := strings.Split(path, "/")
|
||||
|
||||
if len(parts) < 2 {
|
||||
writeValidationError(w, fmt.Errorf("invalid block path"))
|
||||
return
|
||||
}
|
||||
|
||||
// Validate chain ID
|
||||
if err := validateChainID(parts[0], s.chainID); err != nil {
|
||||
writeValidationError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
if parts[1] == "hash" && len(parts) == 3 {
|
||||
// Validate hash format
|
||||
if !isValidHash(parts[2]) {
|
||||
writeValidationError(w, ErrInvalidHash)
|
||||
return
|
||||
}
|
||||
// Get by hash
|
||||
s.handleGetBlockByHash(w, r, parts[2])
|
||||
} else {
|
||||
// Validate and parse block number
|
||||
blockNumber, err := validateBlockNumber(parts[1])
|
||||
if err != nil {
|
||||
writeValidationError(w, err)
|
||||
return
|
||||
}
|
||||
s.handleGetBlockByNumber(w, r, blockNumber)
|
||||
}
|
||||
}
|
||||
|
||||
// handleGetBlockByNumber and handleGetBlockByHash are in blocks.go
|
||||
|
||||
// handleTransactionDetail handles GET /api/v1/transactions/{chain_id}/{hash}
|
||||
func (s *Server) handleTransactionDetail(w http.ResponseWriter, r *http.Request) {
|
||||
path := strings.TrimPrefix(r.URL.Path, "/api/v1/transactions/")
|
||||
parts := strings.Split(path, "/")
|
||||
|
||||
if len(parts) < 2 {
|
||||
writeValidationError(w, fmt.Errorf("invalid transaction path"))
|
||||
return
|
||||
}
|
||||
|
||||
// Validate chain ID
|
||||
if err := validateChainID(parts[0], s.chainID); err != nil {
|
||||
writeValidationError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Validate hash format
|
||||
hash := parts[1]
|
||||
if !isValidHash(hash) {
|
||||
writeValidationError(w, ErrInvalidHash)
|
||||
return
|
||||
}
|
||||
|
||||
s.handleGetTransactionByHash(w, r, hash)
|
||||
}
|
||||
|
||||
// handleGetTransactionByHash is implemented in transactions.go
|
||||
|
||||
// handleAddressDetail handles GET /api/v1/addresses/{chain_id}/{address}
|
||||
func (s *Server) handleAddressDetail(w http.ResponseWriter, r *http.Request) {
|
||||
path := strings.TrimPrefix(r.URL.Path, "/api/v1/addresses/")
|
||||
parts := strings.Split(path, "/")
|
||||
|
||||
if len(parts) < 2 {
|
||||
writeValidationError(w, fmt.Errorf("invalid address path"))
|
||||
return
|
||||
}
|
||||
|
||||
// Validate chain ID
|
||||
if err := validateChainID(parts[0], s.chainID); err != nil {
|
||||
writeValidationError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Validate address format
|
||||
address := parts[1]
|
||||
if !isValidAddress(address) {
|
||||
writeValidationError(w, ErrInvalidAddress)
|
||||
return
|
||||
}
|
||||
|
||||
// Set address in query and call handler
|
||||
r.URL.RawQuery = "address=" + address
|
||||
s.handleGetAddress(w, r)
|
||||
}
|
||||
Reference in New Issue
Block a user