Function bodies 1,118 total
parseSwapsRequest method · go · L634-L671 (38 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) parseSwapsRequest(r *http.Request) (*models.SwapsRequest, error) {
req := &models.SwapsRequest{}
query := r.URL.Query()
if chainIDStr := query.Get("chain_id"); chainIDStr != "" {
chainID, err := strconv.ParseUint(chainIDStr, 10, 64)
if err != nil {
return nil, err
}
req.ChainID = &chainID
}
if address := query.Get("address"); address != "" {
req.Address = &address
}
if limitStr := query.Get("limit"); limitStr != "" {
limit, err := strconv.Atoi(limitStr)
if err != nil {
return nil, err
}
req.Limit = limit
}
if cursorStr := query.Get("cursor"); cursorStr != "" {
cursor, err := strconv.ParseUint(cursorStr, 10, 64)
if err != nil {
return nil, err
}
req.Cursor = &cursor
}
if sort := query.Get("sort"); sort != "" {
req.Sort = sort
}
return req, nil
}parseSearchRequest method · go · L673-L696 (24 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) parseSearchRequest(r *http.Request) (*models.SearchRequest, error) {
req := &models.SearchRequest{}
query := r.URL.Query()
req.Query = strings.TrimSpace(query.Get("q"))
if chainIDStr := query.Get("chain_id"); chainIDStr != "" {
chainID, err := strconv.ParseUint(chainIDStr, 10, 64)
if err != nil {
return nil, err
}
req.ChainID = &chainID
}
if limitStr := query.Get("limit"); limitStr != "" {
limit, err := strconv.Atoi(limitStr)
if err != nil {
return nil, err
}
req.Limit = limit
}
return req, nil
}blockSummaryToDTO method · go · L700-L725 (26 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) blockSummaryToDTO(chainID uint64, chainName string, block *indexer.Block, summary *indexer.BlockSummary) models.BlockSummaryDTO {
var proposerAddr *string
if block.ProposerAddress != "" {
proposerAddr = &block.ProposerAddress
}
numTxs := 0
numEvents := 0
if summary != nil {
numTxs = int(summary.NumTxs)
numEvents = int(summary.NumEvents)
}
return models.BlockSummaryDTO{
ChainID: chainID,
ChainName: chainName,
Height: block.Height,
Hash: block.Hash,
Timestamp: block.Time,
ProposerAddress: proposerAddr,
NumTxs: numTxs,
NumEvents: numEvents,
TotalFees: 0, // Not tracked in BlockSummary
BlockTime: 5.0, // Placeholder: 5 seconds average block time
}
}blockDetailsToDTO method · go · L727-L786 (60 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) blockDetailsToDTO(chainID uint64, block *indexer.Block, summary *indexer.BlockSummary) models.BlockDetailsDTO {
var proposerAddr *string
if block.ProposerAddress != "" {
proposerAddr = &block.ProposerAddress
}
return models.BlockDetailsDTO{
ChainID: chainID,
Height: block.Height,
Hash: block.Hash,
Timestamp: block.Time,
ProposerAddress: proposerAddr,
// Transaction counters
NumTxsSend: int(summary.NumTxsSend),
NumTxsStake: int(summary.NumTxsStake),
NumTxsEditStake: int(summary.NumTxsEditStake),
NumTxsUnstake: int(summary.NumTxsUnstake),
NumTxsPause: int(summary.NumTxsPause),
NumTxsUnpause: int(summary.NumTxsUnpause),
NumTxsChangeParameter: int(summary.NumTxsChangeParameter),
NumTxsDAOTransfer: int(summary.NumTxsDaoTransfer),
NumTxsCertificateResult: int(summary.NumTxsCertificateResults),
NumTxsSubsidy: inttransactionToDTO method · go · L788-L830 (43 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) transactionToDTO(chainID uint64, tx *indexer.Transaction, includeFullMessage bool) models.TransactionDTO {
dto := models.TransactionDTO{
ChainID: chainID,
Height: tx.Height,
TxHash: tx.TxHash,
Timestamp: tx.HeightTime,
MessageType: tx.MessageType,
Signer: tx.Signer,
Counterparty: tx.Counterparty,
Amount: tx.Amount,
Fee: tx.Fee,
Memo: nil, // Memo field not in indexer.Transaction
ValidatorAddress: tx.ValidatorAddress,
DestChainID: tx.ChainID, // ChainID in Transaction is the destination chain
OrderID: tx.OrderID,
PoolID: nil, // PoolID not in indexer.Transaction
SellAssetChainID: nil, // Not separate fields in indexer
BuyAssetChainID: nil, // Not separate fields in indexer
SellAmount: tx.SellAmount,
BuyAmount: tx.BuyAmount,
LimitPrice: tx.Price,
}
// Include full message JSON for detail vGetAddressDetails method · go · L834-L873 (40 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) GetAddressDetails(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
logger := middleware.GetLogger(ctx)
// Parse address from URL
address := chi.URLParam(r, "address")
if address == "" {
response.BadRequest(w, "Address is required", "")
return
}
// Parse query parameters
includeTransactions := r.URL.Query().Get("include_transactions") == "true"
transactionLimit := 10
if limitStr := r.URL.Query().Get("transaction_limit"); limitStr != "" {
if limit, err := strconv.Atoi(limitStr); err == nil && limit > 0 && limit <= 100 {
transactionLimit = limit
}
}
// Build request
req := &models.AddressDetailsRequest{
Address: address,
IncludeTransactions: includeTransactions,
TransactionLimit: transactionLimit,
}
// Get address details from service
details, err := h.explorerSvc.GetAddressDetails(ctx, req)
if err != nil {
logger.Error("failed to get address details",
zap.Error(err),
zap.String("address", aGetNetworkOverview method · go · L877-L926 (50 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) GetNetworkOverview(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
logger := middleware.GetLogger(ctx)
// Parse chain_id query parameter
var chainID *uint64
if chainIDStr := r.URL.Query().Get("chain_id"); chainIDStr != "" {
parsed, err := strconv.ParseUint(chainIDStr, 10, 64)
if err != nil {
response.BadRequest(w, "Invalid chain_id parameter", err.Error())
return
}
chainID = &parsed
}
// Parse start_time query parameter
var startTime *time.Time
if startTimeStr := r.URL.Query().Get("start_time"); startTimeStr != "" {
parsed, err := parseTimeParam(startTimeStr)
if err != nil {
response.BadRequest(w, "Invalid start_time parameter", err.Error())
return
}
startTime = &parsed
}
// Parse end_time query parameter
var endTime *time.Time
if endTimeStr := r.URL.Query().Get("end_time"); endTimeStr != "" {
parsed, err := parseTimeParam(endTimeStr)
if err != nil {
response.BadRequest(w, "Invalid end_time parameAll rows scored by the Repobility analyzer (https://repobility.com)
parseTimeParam function · go · L929-L943 (15 LOC)internal/handlers/explorer.go
func parseTimeParam(timeStr string) (time.Time, error) {
// Try RFC3339 format first (standard format)
t, err := time.Parse(time.RFC3339, timeStr)
if err == nil {
return t, nil
}
// Try RFC3339Nano as fallback
t, err = time.Parse(time.RFC3339Nano, timeStr)
if err == nil {
return t, nil
}
return time.Time{}, fmt.Errorf("invalid time format, expected RFC3339/ISO 8601 (e.g., 2006-01-02T15:04:05Z)")
}GetTrending method · go · L947-L984 (38 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) GetTrending(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
logger := middleware.GetLogger(ctx)
// Parse limit parameter
limit := 20 // Default
if limitStr := r.URL.Query().Get("limit"); limitStr != "" {
parsedLimit, err := strconv.Atoi(limitStr)
if err != nil {
response.BadRequest(w, "Invalid limit parameter", err.Error())
return
}
// Apply bounds
if parsedLimit < 1 {
limit = 1
} else if parsedLimit > 100 {
limit = 100
} else {
limit = parsedLimit
}
}
// Get trending chains from service
trending, err := h.explorerSvc.GetTrending(ctx, limit)
if err != nil {
logger.Error("failed to get trending chains", zap.Error(err))
response.InternalServerError(w, "Failed to retrieve trending chains")
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]interface{}{
"data": trending.Data,
"pagination": trending.Pagination,
})
GetPools method · go · L988-L1037 (50 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) GetPools(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
logger := middleware.GetLogger(ctx)
// Parse query parameters
req, err := h.parsePoolsRequest(r)
if err != nil {
response.BadRequest(w, "Invalid query parameters", err.Error())
return
}
if req == nil {
logger.Error("parsePoolsRequest returned nil request")
response.InternalServerError(w, "Failed to parse request")
return
}
// Set default limit
if req.Limit == 0 {
req.Limit = 20
}
if req.Limit > 100 {
req.Limit = 100
}
// Default sort to descending (most recent first)
if req.Sort == "" {
req.Sort = "desc"
}
// Build query options
opts := h.buildPoolQueryOptions(req)
// Fetch pools from service
pools, pagination, err := h.explorerSvc.GetPools(ctx, opts)
if err != nil {
logger.Error("failed to get pools", zap.Error(err))
response.InternalServerError(w, "Failed to retrieve pools")
return
}
// Prepare response with pagination
responseData := mapGetPool method · go · L1041-L1074 (34 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) GetPool(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
logger := middleware.GetLogger(ctx)
// Parse chain_id from URL
chainIDStr := chi.URLParam(r, "chain_id")
chainID, err := strconv.ParseUint(chainIDStr, 10, 64)
if err != nil {
response.BadRequest(w, "Invalid chain_id", err.Error())
return
}
// Parse pool_id from URL
poolIDStr := chi.URLParam(r, "pool_id")
poolID, err := strconv.ParseUint(poolIDStr, 10, 64)
if err != nil {
response.BadRequest(w, "Invalid pool_id", err.Error())
return
}
// Fetch pool from service
pool, err := h.explorerSvc.GetPool(ctx, chainID, poolID)
if err != nil {
logger.Error("failed to get pool",
zap.Error(err),
zap.Uint64("chain_id", chainID),
zap.Uint64("pool_id", poolID),
)
response.NotFound(w, "Pool not found")
return
}
response.Success(w, http.StatusOK, pool)
}GetLPPositions method · go · L1078-L1127 (50 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) GetLPPositions(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
logger := middleware.GetLogger(ctx)
// Parse query parameters
req, err := h.parseLPPositionsRequest(r)
if err != nil {
response.BadRequest(w, "Invalid query parameters", err.Error())
return
}
if req == nil {
logger.Error("parseLPPositionsRequest returned nil request")
response.InternalServerError(w, "Failed to parse request")
return
}
// Set default limit
if req.Limit == 0 {
req.Limit = 20
}
if req.Limit > 100 {
req.Limit = 100
}
// Default sort to descending (most recent first)
if req.Sort == "" {
req.Sort = "desc"
}
// Build query options
opts := h.buildLPPositionQueryOptions(req)
// Fetch LP positions from service
positions, pagination, err := h.explorerSvc.GetLPPositions(ctx, opts)
if err != nil {
logger.Error("failed to get LP positions", zap.Error(err))
response.InternalServerError(w, "Failed to retrieve LP positions")
return
}
/GetLPPositionsByAddress method · go · L1131-L1199 (69 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) GetLPPositionsByAddress(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
logger := middleware.GetLogger(ctx)
// Parse address from URL
address := chi.URLParam(r, "address")
if address == "" {
response.BadRequest(w, "Address is required", "")
return
}
// Validate address format (40 character hex string)
if matched, _ := regexp.MatchString("^[a-fA-F0-9]{40}$", address); !matched {
response.BadRequest(w, "Invalid address format", "Address must be a 40-character hexadecimal string")
return
}
// Parse optional query parameters
var chainID *uint64
if chainIDStr := r.URL.Query().Get("chain_id"); chainIDStr != "" {
parsed, err := strconv.ParseUint(chainIDStr, 10, 64)
if err != nil {
response.BadRequest(w, "Invalid chain_id", err.Error())
return
}
chainID = &parsed
}
// Parse limit
limit := 50 // Default for address-specific queries
if limitStr := r.URL.Query().Get("limit"); limitStr != "" {
parsedLimit, err := stparsePoolsRequest method · go · L1203-L1244 (42 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) parsePoolsRequest(r *http.Request) (*models.PoolsRequest, error) {
req := &models.PoolsRequest{}
query := r.URL.Query()
if chainIDStr := query.Get("chain_id"); chainIDStr != "" {
chainID, err := strconv.ParseUint(chainIDStr, 10, 64)
if err != nil {
return nil, err
}
req.ChainID = &chainID
}
if poolIDStr := query.Get("pool_id"); poolIDStr != "" {
poolID, err := strconv.ParseUint(poolIDStr, 10, 64)
if err != nil {
return nil, err
}
req.PoolID = &poolID
}
if limitStr := query.Get("limit"); limitStr != "" {
limit, err := strconv.Atoi(limitStr)
if err != nil {
return nil, err
}
req.Limit = limit
}
if cursorStr := query.Get("cursor"); cursorStr != "" {
cursor, err := strconv.ParseUint(cursorStr, 10, 64)
if err != nil {
return nil, err
}
req.Cursor = &cursor
}
if sort := query.Get("sort"); sort != "" {
req.Sort = sort
}
return req, nil
}parseLPPositionsRequest method · go · L1246-L1291 (46 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) parseLPPositionsRequest(r *http.Request) (*models.LPPositionsRequest, error) {
req := &models.LPPositionsRequest{}
query := r.URL.Query()
if chainIDStr := query.Get("chain_id"); chainIDStr != "" {
chainID, err := strconv.ParseUint(chainIDStr, 10, 64)
if err != nil {
return nil, err
}
req.ChainID = &chainID
}
if address := query.Get("address"); address != "" {
req.Address = &address
}
if poolIDStr := query.Get("pool_id"); poolIDStr != "" {
poolID, err := strconv.ParseUint(poolIDStr, 10, 64)
if err != nil {
return nil, err
}
req.PoolID = &poolID
}
if limitStr := query.Get("limit"); limitStr != "" {
limit, err := strconv.Atoi(limitStr)
if err != nil {
return nil, err
}
req.Limit = limit
}
if cursorStr := query.Get("cursor"); cursorStr != "" {
cursor, err := strconv.ParseUint(cursorStr, 10, 64)
if err != nil {
return nil, err
}
req.Cursor = &cursor
}
if sort := query.Get("sort"); sort != "" {
req.SWant this analysis on your repo? https://repobility.com/scan/
buildPoolQueryOptions method · go · L1293-L1310 (18 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) buildPoolQueryOptions(req *models.PoolsRequest) crosschain.QueryOptions {
opts := crosschain.QueryOptions{
Limit: req.Limit,
OrderBy: "height",
Desc: req.Sort == "desc",
Filters: make(map[string]string),
}
if req.ChainID != nil {
opts.ChainIDs = []uint64{*req.ChainID}
}
if req.PoolID != nil {
opts.Filters["pool_id"] = strconv.FormatUint(*req.PoolID, 10)
}
return opts
}buildLPPositionQueryOptions method · go · L1312-L1333 (22 LOC)internal/handlers/explorer.go
func (h *ExplorerHandler) buildLPPositionQueryOptions(req *models.LPPositionsRequest) crosschain.QueryOptions {
opts := crosschain.QueryOptions{
Limit: req.Limit,
OrderBy: "height",
Desc: req.Sort == "desc",
Filters: make(map[string]string),
}
if req.ChainID != nil {
opts.ChainIDs = []uint64{*req.ChainID}
}
if req.Address != nil {
opts.Filters["address"] = *req.Address
}
if req.PoolID != nil {
opts.Filters["pool_id"] = strconv.FormatUint(*req.PoolID, 10)
}
return opts
}HealthCheck function · go · L12-L20 (9 LOC)internal/handlers/health.go
func HealthCheck(w http.ResponseWriter, r *http.Request) {
healthResponse := models.HealthResponse{
Status: "healthy",
Timestamp: time.Now().Format(time.RFC3339),
Version: "1.0.0", // This could come from build info
}
response.Success(w, http.StatusOK, healthResponse)
}NewMetricsHandler function · go · L58-L72 (15 LOC)internal/handlers/metrics.go
func NewMetricsHandler(
dexMetricsRepo DEXMetricsRepository,
orderBookMetricsRepo OrderBookMetricsRepository,
liquidityMetricsRepo LiquidityMetricsRepository,
tradingMetricsRepo TradingMetricsRepository,
validator *validators.Validator,
) *MetricsHandler {
return &MetricsHandler{
dexMetricsRepo: dexMetricsRepo,
orderBookMetricsRepo: orderBookMetricsRepo,
liquidityMetricsRepo: liquidityMetricsRepo,
tradingMetricsRepo: tradingMetricsRepo,
validator: validator,
}
}parseMetricsQueryParams method · go · L86-L155 (70 LOC)internal/handlers/metrics.go
func (h *MetricsHandler) parseMetricsQueryParams(r *http.Request) (*MetricsQueryParams, error) {
params := &MetricsQueryParams{}
// Parse start_time
if startTimeStr := r.URL.Query().Get("start_time"); startTimeStr != "" {
startTime, err := time.Parse(time.RFC3339, startTimeStr)
if err != nil {
return nil, fmt.Errorf("invalid start_time format: must be RFC3339 (ISO 8601)")
}
params.StartTime = &startTime
}
// Parse end_time
if endTimeStr := r.URL.Query().Get("end_time"); endTimeStr != "" {
endTime, err := time.Parse(time.RFC3339, endTimeStr)
if err != nil {
return nil, fmt.Errorf("invalid end_time format: must be RFC3339 (ISO 8601)")
}
params.EndTime = &endTime
}
// Parse granularity
params.Granularity = r.URL.Query().Get("granularity")
if params.Granularity == "" {
params.Granularity = "hourly" // Default
}
// Parse page
if pageStr := r.URL.Query().Get("page"); pageStr != "" {
page, err := strconv.Atoi(pageStr)
if err != nil || page < 1 {
setDefaultTimeRange method · go · L158-L167 (10 LOC)internal/handlers/metrics.go
func (h *MetricsHandler) setDefaultTimeRange(params *MetricsQueryParams) {
now := time.Now()
if params.StartTime == nil {
defaultStart := now.Add(-24 * time.Hour)
params.StartTime = &defaultStart
}
if params.EndTime == nil {
params.EndTime = &now
}
}parsePaginationParams method · go · L170-L194 (25 LOC)internal/handlers/metrics.go
func (h *MetricsHandler) parsePaginationParams(r *http.Request) MetricsPagination {
page := 1
limit := 20
if pageStr := r.URL.Query().Get("page"); pageStr != "" {
if p, err := strconv.Atoi(pageStr); err == nil && p > 0 {
page = p
}
}
if limitStr := r.URL.Query().Get("limit"); limitStr != "" {
if l, err := strconv.Atoi(limitStr); err == nil && l > 0 {
limit = l
if limit > 100 {
limit = 100 // Max limit
}
}
}
return MetricsPagination{
Page: page,
Limit: limit,
Offset: (page - 1) * limit,
}
}GetAllDEXMetrics method · go · L202-L220 (19 LOC)internal/handlers/metrics.go
func (h *MetricsHandler) GetAllDEXMetrics(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
params, err := h.parseMetricsQueryParams(r)
if err != nil {
response.BadRequest(w, "Invalid query parameters", err.Error())
return
}
h.setDefaultTimeRange(params)
metrics, err := h.dexMetricsRepo.GetAllDEXMetricsAcrossChains(ctx, params.StartTime, params.EndTime)
if err != nil {
response.InternalServerError(w, fmt.Sprintf("Failed to retrieve DEX metrics: %s", err.Error()))
return
}
response.Success(w, http.StatusOK, metrics)
}If a scraper extracted this row, it came from Repobility (https://repobility.com)
GetAllDEXMetricsByChain method · go · L224-L248 (25 LOC)internal/handlers/metrics.go
func (h *MetricsHandler) GetAllDEXMetricsByChain(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
chainIDStr := chi.URLParam(r, "chain_id")
chainID, err := strconv.ParseUint(chainIDStr, 10, 64)
if err != nil {
response.Error(w, http.StatusBadRequest, "Invalid chain ID", "")
return
}
params, err := h.parseMetricsQueryParams(r)
if err != nil {
response.BadRequest(w, "Invalid query parameters", err.Error())
return
}
h.setDefaultTimeRange(params)
metrics, err := h.dexMetricsRepo.GetAllDEXMetrics(ctx, chainID, params.StartTime, params.EndTime)
if err != nil {
response.InternalServerError(w, fmt.Sprintf("Failed to retrieve DEX metrics: %s", err.Error()))
return
}
response.Success(w, http.StatusOK, metrics)
}GetLPHoldings method · go · L255-L276 (22 LOC)internal/handlers/metrics.go
func (h *MetricsHandler) GetLPHoldings(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
params, err := h.parseMetricsQueryParams(r)
if err != nil {
response.BadRequest(w, "Invalid query parameters", err.Error())
return
}
if params.Address == "" {
response.BadRequest(w, "Missing required parameter", "address query parameter is required")
return
}
metrics, err := h.liquidityMetricsRepo.GetLPHoldings(ctx, params.Address)
if err != nil {
response.InternalServerError(w, fmt.Sprintf("Failed to retrieve LP holdings: %s", err.Error()))
return
}
response.Success(w, http.StatusOK, metrics)
}GetAllLiquidityMetrics method · go · L286-L321 (36 LOC)internal/handlers/metrics.go
func (h *MetricsHandler) GetAllLiquidityMetrics(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
params, err := h.parseMetricsQueryParams(r)
if err != nil {
response.BadRequest(w, "Invalid query parameters", err.Error())
return
}
h.setDefaultTimeRange(params)
// Parse optional pool_id query parameter
var poolID *uint64
if poolIDStr := r.URL.Query().Get("pool_id"); poolIDStr != "" {
pid, err := strconv.ParseUint(poolIDStr, 10, 64)
if err != nil {
response.BadRequest(w, "Invalid pool_id parameter", err.Error())
return
}
poolID = &pid
}
// Default granularity if not specified
granularity := models.TimeGranularity(params.Granularity)
if params.Granularity == "" {
granularity = models.GranularityHourly
}
metrics, err := h.liquidityMetricsRepo.GetAllLiquidityMetricsAcrossChains(ctx, poolID, params.StartTime, params.EndTime, granularity)
if err != nil {
response.InternalServerError(w, fmt.Sprintf("Failed to retrieve liquidity metrics: %s",GetAllLiquidityMetricsByChain method · go · L325-L366 (42 LOC)internal/handlers/metrics.go
func (h *MetricsHandler) GetAllLiquidityMetricsByChain(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
chainIDStr := chi.URLParam(r, "chain_id")
chainID, err := strconv.ParseUint(chainIDStr, 10, 64)
if err != nil {
response.Error(w, http.StatusBadRequest, "Invalid chain ID", "")
return
}
params, err := h.parseMetricsQueryParams(r)
if err != nil {
response.BadRequest(w, "Invalid query parameters", err.Error())
return
}
h.setDefaultTimeRange(params)
// Parse optional pool_id query parameter
var poolID *uint64
if poolIDStr := r.URL.Query().Get("pool_id"); poolIDStr != "" {
pid, err := strconv.ParseUint(poolIDStr, 10, 64)
if err != nil {
response.BadRequest(w, "Invalid pool_id parameter", err.Error())
return
}
poolID = &pid
}
// Default granularity if not specified
granularity := models.TimeGranularity(params.Granularity)
if params.Granularity == "" {
granularity = models.GranularityHourly
}
metrics, err := h.liquidityMetricsRepo.GetAllTradingMetrics method · go · L378-L404 (27 LOC)internal/handlers/metrics.go
func (h *MetricsHandler) GetAllTradingMetrics(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
params, err := h.parseMetricsQueryParams(r)
if err != nil {
response.BadRequest(w, "Invalid query parameters", err.Error())
return
}
h.setDefaultTimeRange(params)
// Parse optional query parameters
rankBy := r.URL.Query().Get("rank_by")
if rankBy == "" {
rankBy = "volume" // Default to volume ranking
}
pagination := h.parsePaginationParams(r)
metrics, err := h.tradingMetricsRepo.GetAllTradingMetricsAcrossChains(ctx, params.StartTime, params.EndTime, rankBy, pagination)
if err != nil {
response.InternalServerError(w, fmt.Sprintf("Failed to retrieve trading metrics: %s", err.Error()))
return
}
response.Success(w, http.StatusOK, metrics)
}GetAllTradingMetricsByChain method · go · L408-L440 (33 LOC)internal/handlers/metrics.go
func (h *MetricsHandler) GetAllTradingMetricsByChain(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
chainIDStr := chi.URLParam(r, "chain_id")
chainID, err := strconv.ParseUint(chainIDStr, 10, 64)
if err != nil {
response.Error(w, http.StatusBadRequest, "Invalid chain ID", "")
return
}
params, err := h.parseMetricsQueryParams(r)
if err != nil {
response.BadRequest(w, "Invalid query parameters", err.Error())
return
}
h.setDefaultTimeRange(params)
// Parse optional query parameters
rankBy := r.URL.Query().Get("rank_by")
if rankBy == "" {
rankBy = "volume" // Default to volume ranking
}
pagination := h.parsePaginationParams(r)
metrics, err := h.tradingMetricsRepo.GetAllTradingMetrics(ctx, chainID, params.StartTime, params.EndTime, rankBy, pagination)
if err != nil {
response.InternalServerError(w, fmt.Sprintf("Failed to retrieve trading metrics: %s", err.Error()))
return
}
response.Success(w, http.StatusOK, metrics)
}GetAllOrderbookMetrics method · go · L448-L466 (19 LOC)internal/handlers/metrics.go
func (h *MetricsHandler) GetAllOrderbookMetrics(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
params, err := h.parseMetricsQueryParams(r)
if err != nil {
response.BadRequest(w, "Invalid query parameters", err.Error())
return
}
h.setDefaultTimeRange(params)
metrics, err := h.orderBookMetricsRepo.GetAllOrderbookMetricsAcrossChains(ctx, params.StartTime, params.EndTime)
if err != nil {
response.InternalServerError(w, fmt.Sprintf("Failed to retrieve orderbook metrics: %s", err.Error()))
return
}
response.Success(w, http.StatusOK, metrics)
}GetAllOrderbookMetricsByChain method · go · L470-L494 (25 LOC)internal/handlers/metrics.go
func (h *MetricsHandler) GetAllOrderbookMetricsByChain(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
chainIDStr := chi.URLParam(r, "chain_id")
chainID, err := strconv.ParseUint(chainIDStr, 10, 64)
if err != nil {
response.Error(w, http.StatusBadRequest, "Invalid chain ID", "")
return
}
params, err := h.parseMetricsQueryParams(r)
if err != nil {
response.BadRequest(w, "Invalid query parameters", err.Error())
return
}
h.setDefaultTimeRange(params)
metrics, err := h.orderBookMetricsRepo.GetAllOrderbookMetrics(ctx, chainID, params.StartTime, params.EndTime)
if err != nil {
response.InternalServerError(w, fmt.Sprintf("Failed to retrieve orderbook metrics: %s", err.Error()))
return
}
response.Success(w, http.StatusOK, metrics)
}Repobility · open methodology · https://repobility.com/research/
NewParamsHandler function · go · L22-L28 (7 LOC)internal/handlers/params.go
func NewParamsHandler(rpcClient *canopy.Client, validator *validators.Validator, logger *zap.Logger) *ParamsHandler {
return &ParamsHandler{
rpcClient: rpcClient,
validator: validator,
logger: logger,
}
}parseHeightParam function · go · L32-L42 (11 LOC)internal/handlers/params.go
func parseHeightParam(r *http.Request) uint64 {
heightStr := r.URL.Query().Get("height")
if heightStr == "" {
return 0
}
height, err := strconv.ParseUint(heightStr, 10, 64)
if err != nil {
return 0
}
return height
}GetFeeParams method · go · L45-L73 (29 LOC)internal/handlers/params.go
func (h *ParamsHandler) GetFeeParams(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// Parse optional height query parameter (default: 0 = latest)
height := parseHeightParam(r)
// Call RPC client
params, libErr := h.rpcClient.FeeParams(height)
if libErr != nil {
custommiddleware.GetLogger(ctx).Error("failed to query fee params",
zap.Error(libErr),
zap.Uint64("height", height),
)
response.InternalServerError(w, "Failed to query fee parameters")
return
}
// Check for nil response
if params == nil {
custommiddleware.GetLogger(ctx).Error("received nil fee params",
zap.Uint64("height", height),
)
response.InternalServerError(w, "Failed to query fee parameters")
return
}
// Return JSON response
response.Success(w, http.StatusOK, params)
}GetGovParams method · go · L76-L104 (29 LOC)internal/handlers/params.go
func (h *ParamsHandler) GetGovParams(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// Parse optional height query parameter (default: 0 = latest)
height := parseHeightParam(r)
// Call RPC client
params, libErr := h.rpcClient.GovParams(height)
if libErr != nil {
custommiddleware.GetLogger(ctx).Error("failed to query governance params",
zap.Error(libErr),
zap.Uint64("height", height),
)
response.InternalServerError(w, "Failed to query governance parameters")
return
}
// Check for nil response
if params == nil {
custommiddleware.GetLogger(ctx).Error("received nil governance params",
zap.Uint64("height", height),
)
response.InternalServerError(w, "Failed to query governance parameters")
return
}
// Return JSON response
response.Success(w, http.StatusOK, params)
}GetConParams method · go · L107-L135 (29 LOC)internal/handlers/params.go
func (h *ParamsHandler) GetConParams(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// Parse optional height query parameter (default: 0 = latest)
height := parseHeightParam(r)
// Call RPC client
params, libErr := h.rpcClient.ConParams(height)
if libErr != nil {
custommiddleware.GetLogger(ctx).Error("failed to query consensus params",
zap.Error(libErr),
zap.Uint64("height", height),
)
response.InternalServerError(w, "Failed to query consensus parameters")
return
}
// Check for nil response
if params == nil {
custommiddleware.GetLogger(ctx).Error("received nil consensus params",
zap.Uint64("height", height),
)
response.InternalServerError(w, "Failed to query consensus parameters")
return
}
// Return JSON response
response.Success(w, http.StatusOK, params)
}GetValParams method · go · L138-L166 (29 LOC)internal/handlers/params.go
func (h *ParamsHandler) GetValParams(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// Parse optional height query parameter (default: 0 = latest)
height := parseHeightParam(r)
// Call RPC client
params, libErr := h.rpcClient.ValParams(height)
if libErr != nil {
custommiddleware.GetLogger(ctx).Error("failed to query validator params",
zap.Error(libErr),
zap.Uint64("height", height),
)
response.InternalServerError(w, "Failed to query validator parameters")
return
}
// Check for nil response
if params == nil {
custommiddleware.GetLogger(ctx).Error("received nil validator params",
zap.Uint64("height", height),
)
response.InternalServerError(w, "Failed to query validator parameters")
return
}
// Return JSON response
response.Success(w, http.StatusOK, params)
}NewPortfolioHandler function · go · L21-L27 (7 LOC)internal/handlers/portfolio.go
func NewPortfolioHandler(portfolioService *portfolio.Service, validator *validators.Validator, logger *zap.Logger) *PortfolioHandler {
return &PortfolioHandler{
portfolioService: portfolioService,
validator: validator,
logger: logger,
}
}GetPortfolioOverview method · go · L30-L54 (25 LOC)internal/handlers/portfolio.go
func (h *PortfolioHandler) GetPortfolioOverview(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var req models.PortfolioOverviewRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
response.BadRequest(w, "Invalid JSON payload", err.Error())
return
}
// Get portfolio overview
overview, err := h.portfolioService.GetPortfolioOverview(ctx, &req)
if err != nil {
if err == portfolio.ErrNoAddressesProvided {
response.BadRequest(w, "No addresses provided", err.Error())
return
}
middleware.GetLogger(ctx).Error("failed to get portfolio overview",
zap.Error(err),
)
response.InternalServerError(w, "Failed to retrieve portfolio overview")
return
}
response.Success(w, http.StatusOK, overview)
}All rows scored by the Repobility analyzer (https://repobility.com)
GetAccountBalances method · go · L57-L81 (25 LOC)internal/handlers/portfolio.go
func (h *PortfolioHandler) GetAccountBalances(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var req models.AccountBalancesRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
response.BadRequest(w, "Invalid JSON payload", err.Error())
return
}
// Get account balances
balances, err := h.portfolioService.GetAccountBalances(ctx, &req)
if err != nil {
if err == portfolio.ErrNoAddressesProvided {
response.BadRequest(w, "No addresses provided", err.Error())
return
}
middleware.GetLogger(ctx).Error("failed to get account balances",
zap.Error(err),
)
response.InternalServerError(w, "Failed to retrieve account balances")
return
}
response.Success(w, http.StatusOK, balances)
}GetPortfolioPerformance method · go · L84-L126 (43 LOC)internal/handlers/portfolio.go
func (h *PortfolioHandler) GetPortfolioPerformance(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var req models.PortfolioPerformanceRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
response.BadRequest(w, "Invalid JSON payload", err.Error())
return
}
// Set defaults
if req.Period == "" {
req.Period = "30d"
}
if req.Granularity == "" {
req.Granularity = "daily"
}
// Get portfolio performance
performance, err := h.portfolioService.GetPortfolioPerformance(ctx, &req)
if err != nil {
if err == portfolio.ErrNoAddressesProvided {
response.BadRequest(w, "No addresses provided", err.Error())
return
}
if err == portfolio.ErrInvalidPeriod {
response.BadRequest(w, "Invalid period", err.Error())
return
}
if err == portfolio.ErrInvalidGranularity {
response.BadRequest(w, "Invalid granularity", err.Error())
return
}
middleware.GetLogger(ctx).Error("failed to get portfolio performance",
zap.Error(err),
zap.SGetAssetAllocation method · go · L129-L153 (25 LOC)internal/handlers/portfolio.go
func (h *PortfolioHandler) GetAssetAllocation(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var req models.AssetAllocationRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
response.BadRequest(w, "Invalid JSON payload", err.Error())
return
}
// Get asset allocation
allocation, err := h.portfolioService.GetAssetAllocation(ctx, &req)
if err != nil {
if err == portfolio.ErrNoAddressesProvided {
response.BadRequest(w, "No addresses provided", err.Error())
return
}
middleware.GetLogger(ctx).Error("failed to get asset allocation",
zap.Error(err),
)
response.InternalServerError(w, "Failed to retrieve asset allocation")
return
}
response.Success(w, http.StatusOK, allocation)
}GetMultiChainBalance method · go · L156-L180 (25 LOC)internal/handlers/portfolio.go
func (h *PortfolioHandler) GetMultiChainBalance(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var req models.MultiChainBalanceRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
response.BadRequest(w, "Invalid JSON payload", err.Error())
return
}
// Get multi-chain balance
balance, err := h.portfolioService.GetMultiChainBalance(ctx, &req)
if err != nil {
if err == portfolio.ErrNoAddressesProvided {
response.BadRequest(w, "No addresses provided", err.Error())
return
}
middleware.GetLogger(ctx).Error("failed to get multi-chain balance",
zap.Error(err),
)
response.InternalServerError(w, "Failed to retrieve multi-chain balance")
return
}
response.Success(w, http.StatusOK, balance)
}ListRoutes function · go · L18-L39 (22 LOC)internal/handlers/routes.go
func ListRoutes(router *chi.Mux) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var routes []RouteInfo
// Walk through all registered routes
chi.Walk(router, func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error {
routes = append(routes, RouteInfo{
Method: method,
Path: route,
Middlewares: len(middlewares),
})
return nil
})
// Return routes as JSON
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{
"data": routes,
"count": len(routes),
})
}
}NewStakingHandler function · go · L20-L25 (6 LOC)internal/handlers/staking.go
func NewStakingHandler(stakingService *staking.Service, logger *zap.Logger) *StakingHandler {
return &StakingHandler{
stakingService: stakingService,
logger: logger,
}
}GetStakingPositions method · go · L29-L64 (36 LOC)internal/handlers/staking.go
func (h *StakingHandler) GetStakingPositions(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// Get authenticated user ID from context
userIDStr, ok := ctx.Value("userID").(string)
if !ok {
response.Unauthorized(w, "Authentication required")
return
}
userID, err := uuid.Parse(userIDStr)
if err != nil {
response.BadRequest(w, "Invalid user ID", err.Error())
return
}
// Parse query parameters
req, err := h.parseQueryParams(r)
if err != nil {
response.BadRequest(w, "Invalid query parameters", err.Error())
return
}
// Get staking positions
positionsResp, err := h.stakingService.GetStakingPositions(ctx, userID, req)
if err != nil {
h.logger.Error("failed to get staking positions",
zap.Error(err),
zap.String("user_id", userID.String()),
)
response.InternalServerError(w, "Failed to get staking positions")
return
}
response.Success(w, http.StatusOK, positionsResp)
}parseQueryParams method · go · L67-L108 (42 LOC)internal/handlers/staking.go
func (h *StakingHandler) parseQueryParams(r *http.Request) (*models.StakingPositionsRequest, error) {
req := &models.StakingPositionsRequest{}
// Parse chain_ids (comma-separated)
if chainIDsStr := r.URL.Query().Get("chain_ids"); chainIDsStr != "" {
chainIDParts := strings.Split(chainIDsStr, ",")
chainIDs := make([]uint64, 0, len(chainIDParts))
for _, part := range chainIDParts {
chainID, err := strconv.ParseUint(strings.TrimSpace(part), 10, 64)
if err != nil {
return nil, err
}
chainIDs = append(chainIDs, chainID)
}
req.ChainIDs = chainIDs
}
// Parse status filter
if status := r.URL.Query().Get("status"); status != "" {
req.Status = status
}
// Parse limit
if limitStr := r.URL.Query().Get("limit"); limitStr != "" {
limit, err := strconv.Atoi(limitStr)
if err != nil {
return nil, err
}
req.Limit = limit
}
// Parse offset
if offsetStr := r.URL.Query().Get("offset"); offsetStr != "" {
offset, err := strconv.ParseUint(offsetStr, 10,Want this analysis on your repo? https://repobility.com/scan/
GetStakingRewards method · go · L112-L147 (36 LOC)internal/handlers/staking.go
func (h *StakingHandler) GetStakingRewards(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// Get authenticated user ID from context
userIDStr, ok := ctx.Value("userID").(string)
if !ok {
response.Unauthorized(w, "Authentication required")
return
}
userID, err := uuid.Parse(userIDStr)
if err != nil {
response.BadRequest(w, "Invalid user ID", err.Error())
return
}
// Parse query parameters
req, err := h.parseRewardsQueryParams(r)
if err != nil {
response.BadRequest(w, "Invalid query parameters", err.Error())
return
}
// Get staking rewards
rewardsResp, err := h.stakingService.GetStakingRewards(ctx, userID, req)
if err != nil {
h.logger.Error("failed to get staking rewards",
zap.Error(err),
zap.String("user_id", userID.String()),
)
response.InternalServerError(w, "Failed to get staking rewards")
return
}
response.Success(w, http.StatusOK, rewardsResp)
}GetUnstakingQueue method · go · L151-L186 (36 LOC)internal/handlers/staking.go
func (h *StakingHandler) GetUnstakingQueue(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// Get authenticated user ID from context
userIDStr, ok := ctx.Value("userID").(string)
if !ok {
response.Unauthorized(w, "Authentication required")
return
}
userID, err := uuid.Parse(userIDStr)
if err != nil {
response.BadRequest(w, "Invalid user ID", err.Error())
return
}
// Parse query parameters
req, err := h.parseUnstakingQueryParams(r)
if err != nil {
response.BadRequest(w, "Invalid query parameters", err.Error())
return
}
// Get unstaking queue
queueResp, err := h.stakingService.GetUnstakingQueue(ctx, userID, req)
if err != nil {
h.logger.Error("failed to get unstaking queue",
zap.Error(err),
zap.String("user_id", userID.String()),
)
response.InternalServerError(w, "Failed to get unstaking queue")
return
}
response.Success(w, http.StatusOK, queueResp)
}parseRewardsQueryParams method · go · L189-L225 (37 LOC)internal/handlers/staking.go
func (h *StakingHandler) parseRewardsQueryParams(r *http.Request) (*models.StakingRewardsRequest, error) {
req := &models.StakingRewardsRequest{}
// Parse chain_ids (comma-separated)
if chainIDsStr := r.URL.Query().Get("chain_ids"); chainIDsStr != "" {
chainIDParts := strings.Split(chainIDsStr, ",")
chainIDs := make([]uint64, 0, len(chainIDParts))
for _, part := range chainIDParts {
chainID, err := strconv.ParseUint(strings.TrimSpace(part), 10, 64)
if err != nil {
return nil, err
}
chainIDs = append(chainIDs, chainID)
}
req.ChainIDs = chainIDs
}
// Parse limit
if limitStr := r.URL.Query().Get("limit"); limitStr != "" {
limit, err := strconv.Atoi(limitStr)
if err != nil {
return nil, err
}
req.Limit = limit
}
// Parse offset
if offsetStr := r.URL.Query().Get("offset"); offsetStr != "" {
offset, err := strconv.ParseUint(offsetStr, 10, 64)
if err != nil {
return nil, err
}
req.Offset = offset
}
return req, nil
}