-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
### TL;DR Implemented new API endpoints for transactions and events, enhanced query parameter handling, and improved error responses. ### What changed? - Added new API endpoints for transactions and events, including chain-specific, contract-specific, and function signature-specific routes. - Implemented `ParseQueryParams` function to handle complex query parameters, including filtering, grouping, sorting, and pagination. - Enhanced error handling with more specific error types (BadRequest, Unauthorized, Internal). - Updated the `QueryResponse` and `Meta` structs to include more detailed information about the query results. - Added a health check endpoint. - Removed the `GetBlocks` handler and replaced it with more specific transaction and event handlers. - Updated dependencies, including upgrading chi and gorilla/schema. ### How to test? 1. Run the API server locally. 2. Test the new endpoints: - GET /api/transactions/{chainId} - GET /api/events/{chainId} - GET /api/transactions/{chainId}/{contractAddress} - GET /api/events/{chainId}/{contractAddress} - GET /api/transactions/{chainId}/{contractAddress}/{functionSig} - GET /api/events/{chainId}/{contractAddress}/{functionSig} 3. Test the health check endpoint: GET /health 4. Verify that query parameters are correctly parsed and included in the response. 5. Test error scenarios, including unauthorized access and invalid chain IDs. ### Why make this change? This change aims to provide a more flexible and powerful API for querying blockchain data. The new endpoints allow for more granular queries, while the enhanced query parameter handling supports advanced filtering, sorting, and aggregation. The improved error handling and response structure will make it easier for clients to consume and understand the API responses.
- Loading branch information
Showing
10 changed files
with
340 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,34 @@ | ||
package handlers | ||
|
||
import ( | ||
"net/http" | ||
|
||
chimiddle "github.com/go-chi/chi/middleware" | ||
"github.com/go-chi/chi/v5" | ||
"github.com/thirdweb-dev/indexer/internal/middleware" | ||
) | ||
|
||
func Handler(r *chi.Mux) { | ||
r.Use(chimiddle.StripSlashes) | ||
r.Use(middleware.Authorization) | ||
r.Route("/", func(router chi.Router) { | ||
// might consolidate all variants to one handler function | ||
// Wild card queries | ||
router.Get("/{chainId}/transactions", GetTransactions) | ||
router.Get("/{chainId}/events", GetLogs) | ||
|
||
// contract scoped queries | ||
router.Get("/{chainId}/transactions/{contractAddress}", GetTransactionsWithContract) | ||
router.Get("/{chainId}/events/{contractAddress}", GetEventsWithContract) | ||
|
||
// signature scoped queries | ||
router.Get("/{chainId}/transactions/{contractAddress}/{functionSig}", GetTransactionsWithContractAndSignature) | ||
router.Get("/{chainId}/events/{contractAddress}/{functionSig}", GetEventsWithContractAndSignature) | ||
}) | ||
|
||
r.Route("/api", func(router chi.Router) { | ||
router.Use(middleware.Authorization) | ||
router.Route("/v1", func(r chi.Router) { | ||
r.Get("/blocks", GetBlocks) | ||
}) | ||
r.Get("/health", func(w http.ResponseWriter, r *http.Request) { | ||
// TODO: implement a simple query before going live | ||
w.WriteHeader(http.StatusOK) | ||
w.Write([]byte("ok")) | ||
}) | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package handlers | ||
|
||
import ( | ||
"encoding/json" | ||
"net/http" | ||
|
||
"github.com/go-chi/chi/v5" | ||
"github.com/rs/zerolog/log" | ||
"github.com/thirdweb-dev/indexer/api" | ||
) | ||
|
||
func GetLogs(w http.ResponseWriter, r *http.Request) { | ||
chainId, err := api.GetChainId(r) | ||
if err != nil { | ||
api.BadRequestErrorHandler(w, err) | ||
return | ||
} | ||
queryParams, err := api.ParseQueryParams(r) | ||
if err != nil { | ||
api.BadRequestErrorHandler(w, err) | ||
return | ||
} | ||
|
||
var response = api.QueryResponse{ | ||
Meta: api.Meta{ | ||
ChainIdentifier: chainId, | ||
ContractAddress: "todo", | ||
FunctionSig: "todo", | ||
Page: 1, | ||
Limit: 100, | ||
TotalItems: 0, | ||
TotalPages: 0, | ||
}, | ||
Data: []interface{}{queryParams}, | ||
} | ||
|
||
w.Header().Set("Content-Type", "application/json") | ||
err = json.NewEncoder(w).Encode(response) | ||
if err != nil { | ||
log.Error().Err(err).Msg("Error encoding response") | ||
api.InternalErrorHandler(w) | ||
return | ||
} | ||
} | ||
|
||
func GetEventsWithContract(w http.ResponseWriter, r *http.Request) { | ||
chainId, err := api.GetChainId(r) | ||
if err != nil { | ||
api.BadRequestErrorHandler(w, err) | ||
return | ||
} | ||
contractAddress := chi.URLParam(r, "contractAddress") | ||
queryParams, err := api.ParseQueryParams(r) | ||
if err != nil { | ||
api.BadRequestErrorHandler(w, err) | ||
return | ||
} | ||
|
||
var response = api.QueryResponse{ | ||
Meta: api.Meta{ | ||
ChainIdentifier: chainId, | ||
ContractAddress: contractAddress, | ||
FunctionSig: "todo", | ||
Page: 1, | ||
Limit: 100, | ||
TotalItems: 0, | ||
TotalPages: 0, | ||
}, | ||
Data: []interface{}{queryParams}, | ||
} | ||
|
||
w.Header().Set("Content-Type", "application/json") | ||
err = json.NewEncoder(w).Encode(response) | ||
if err != nil { | ||
log.Error().Err(err).Msg("Error encoding response") | ||
api.InternalErrorHandler(w) | ||
return | ||
} | ||
|
||
} | ||
|
||
func GetEventsWithContractAndSignature(w http.ResponseWriter, r *http.Request) { | ||
chainId, err := api.GetChainId(r) | ||
if err != nil { | ||
api.BadRequestErrorHandler(w, err) | ||
return | ||
} | ||
contractAddress := chi.URLParam(r, "contractAddress") | ||
functionSig := chi.URLParam(r, "functionSig") | ||
queryParams, err := api.ParseQueryParams(r) | ||
if err != nil { | ||
api.BadRequestErrorHandler(w, err) | ||
return | ||
} | ||
|
||
var response = api.QueryResponse{ | ||
Meta: api.Meta{ | ||
ChainIdentifier: chainId, | ||
ContractAddress: contractAddress, | ||
FunctionSig: functionSig, | ||
Page: 1, | ||
Limit: 100, | ||
TotalItems: 0, | ||
TotalPages: 0, | ||
}, | ||
Data: []interface{}{queryParams}, | ||
Aggregations: map[string]interface{}{ | ||
"count": 100, | ||
"sum_value": "1000000000000000000000", | ||
"avg_gas_price": "20000000000", | ||
}, | ||
} | ||
|
||
w.Header().Set("Content-Type", "application/json") | ||
err = json.NewEncoder(w).Encode(response) | ||
if err != nil { | ||
log.Error().Err(err).Msg("Error encoding response") | ||
api.InternalErrorHandler(w) | ||
return | ||
} | ||
} |
Oops, something went wrong.