api.go 2.78 KB
Newer Older
1 2 3 4
package api

import (
	"encoding/json"
Will Cory's avatar
Will Cory committed
5 6
	"net/http"

Will Cory's avatar
Will Cory committed
7 8
	"github.com/ethereum-optimism/optimism/indexer/database"
	"github.com/ethereum/go-ethereum/common"
9
	"github.com/go-chi/chi/v5"
10 11 12 13 14 15 16 17 18
)

type PaginationResponse struct {
	// TODO type this better
	Data        interface{} `json:"data"`
	Cursor      string      `json:"cursor"`
	HasNextPage bool        `json:"hasNextPage"`
}

19
func (a *Api) DepositsHandler(w http.ResponseWriter, r *http.Request) {
Will Cory's avatar
Will Cory committed
20 21 22
	bv := a.bridgeView

	address := common.HexToAddress(chi.URLParam(r, "address"))
23

Will Cory's avatar
Will Cory committed
24 25 26 27 28
	// limit := getIntFromQuery(r, "limit", 10)
	// cursor := r.URL.Query().Get("cursor")
	// sortDirection := r.URL.Query().Get("sortDirection")

	deposits, err := bv.DepositsByAddress(address)
29 30 31 32 33 34

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

Will Cory's avatar
Will Cory committed
35 36
	// This is not the shape of the response we want!!!
	// will add in the individual features in future prs 1 by 1
37
	response := PaginationResponse{
Will Cory's avatar
Will Cory committed
38 39 40
		Data: deposits,
		// Cursor:      nextCursor,
		HasNextPage: false,
41
	}
42 43

	jsonResponse(w, response, http.StatusOK)
44 45
}

46
func (a *Api) WithdrawalsHandler(w http.ResponseWriter, r *http.Request) {
Will Cory's avatar
Will Cory committed
47 48 49 50 51 52 53 54 55
	bv := a.bridgeView

	address := common.HexToAddress(chi.URLParam(r, "address"))

	// limit := getIntFromQuery(r, "limit", 10)
	// cursor := r.URL.Query().Get("cursor")
	// sortDirection := r.URL.Query().Get("sortDirection")

	withdrawals, err := bv.WithdrawalsByAddress(address)
56 57 58 59

	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
60
	}
61

Will Cory's avatar
Will Cory committed
62 63
	// This is not the shape of the response we want!!!
	// will add in the individual features in future prs 1 by 1
64
	response := PaginationResponse{
Will Cory's avatar
Will Cory committed
65 66 67
		Data: withdrawals,
		// Cursor:      nextCursor,
		HasNextPage: false,
68 69 70
	}

	jsonResponse(w, response, http.StatusOK)
71 72
}

73 74 75 76
func (a *Api) HealthzHandler(w http.ResponseWriter, r *http.Request) {
	jsonResponse(w, "ok", http.StatusOK)
}

77 78 79
func jsonResponse(w http.ResponseWriter, data interface{}, statusCode int) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(statusCode)
Will Cory's avatar
Will Cory committed
80 81 82
	if err := json.NewEncoder(w).Encode(data); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
83 84 85
}

type Api struct {
Will Cory's avatar
Will Cory committed
86 87
	Router     *chi.Mux
	bridgeView database.BridgeView
88 89
}

Will Cory's avatar
Will Cory committed
90
func NewApi(bv database.BridgeView) *Api {
91 92
	r := chi.NewRouter()

93
	api := &Api{
Will Cory's avatar
Will Cory committed
94 95
		Router:     r,
		bridgeView: bv,
96
	}
Will Cory's avatar
Will Cory committed
97 98 99 100 101
	// these regex are .+ because I wasn't sure what they should be
	// don't want a regex for addresses because would prefer to validate the address
	// with go-ethereum and throw a friendly error message
	r.Get("/api/v0/deposits/{address:.+}", api.DepositsHandler)
	r.Get("/api/v0/withdrawals/{address:.+}", api.WithdrawalsHandler)
102
	r.Get("/healthz", api.HealthzHandler)
103 104 105

	return api

106 107
}

108 109
func (a *Api) Listen(port string) error {
	return http.ListenAndServe(port, a.Router)
110
}