api.go 2.85 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"`
}

Hamdi Allam's avatar
Hamdi Allam committed
19 20
func (a *Api) L1DepositsHandler(w http.ResponseWriter, r *http.Request) {
	bv := a.BridgeTransfersView
Will Cory's avatar
Will Cory committed
21
	address := common.HexToAddress(chi.URLParam(r, "address"))
22

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

Hamdi Allam's avatar
Hamdi Allam committed
27
	deposits, err := bv.L1BridgeDepositsByAddress(address)
28 29 30 31 32
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

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

	jsonResponse(w, response, http.StatusOK)
42 43
}

Hamdi Allam's avatar
Hamdi Allam committed
44 45
func (a *Api) L2WithdrawalsHandler(w http.ResponseWriter, r *http.Request) {
	bv := a.BridgeTransfersView
Will Cory's avatar
Will Cory committed
46 47 48 49 50 51
	address := common.HexToAddress(chi.URLParam(r, "address"))

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

Hamdi Allam's avatar
Hamdi Allam committed
52
	withdrawals, err := bv.L2BridgeWithdrawalsByAddress(address)
53 54 55
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
56
	}
57

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

	jsonResponse(w, response, http.StatusOK)
67 68
}

69 70 71 72
func (a *Api) HealthzHandler(w http.ResponseWriter, r *http.Request) {
	jsonResponse(w, "ok", http.StatusOK)
}

73 74 75
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
76 77 78
	if err := json.NewEncoder(w).Encode(data); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
79 80 81
}

type Api struct {
Hamdi Allam's avatar
Hamdi Allam committed
82 83
	Router              *chi.Mux
	BridgeTransfersView database.BridgeTransfersView
84 85
}

Hamdi Allam's avatar
Hamdi Allam committed
86
func NewApi(bv database.BridgeTransfersView) *Api {
87 88
	r := chi.NewRouter()

Hamdi Allam's avatar
Hamdi Allam committed
89 90
	api := &Api{Router: r, BridgeTransfersView: bv}

Will Cory's avatar
Will Cory committed
91 92 93
	// 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
Hamdi Allam's avatar
Hamdi Allam committed
94 95
	r.Get("/api/v0/deposits/{address:.+}", api.L1DepositsHandler)
	r.Get("/api/v0/withdrawals/{address:.+}", api.L2WithdrawalsHandler)
96
	r.Get("/healthz", api.HealthzHandler)
97 98 99

	return api

100 101
}

102 103
func (a *Api) Listen(port string) error {
	return http.ListenAndServe(port, a.Router)
104
}