arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/api/api.go
api/api.goRaw
  1/*
  2Package api implements the public interface of the hermez-node using a HTTP REST API.
  3There are two subsets of endpoints:
  4- coordinatorEndpoints: used to receive L2 transactions and account creation authorizations. Targeted for wallets.
  5- explorerEndpoints: used to provide all sorts of information about the network. Targeted for explorers and similar services.
  6
  7About the configuration of the API:
  8- The API is supposed to be launched using the cli found at the package cli/node, and configured through the configuration file.
  9- The mentioned configuration file allows exposing any combination of the endpoint subsets.
 10- Although the API can run in a "standalone" manner using the serveapi command, it won't work properly
 11unless another process acting as a coord or sync is filling the HistoryDB.
 12
 13Design principles and considerations:
 14- In order to decouple the API process from the rest of the node, all the communication between this package and the rest of
 15the system is done through the SQL database. As a matter of fact, the only public function of the package is the constructor NewAPI.
 16All the information needed for the API to work should be obtained through the configuration file of the cli or the database.
 17- The format of the requests / responses doesn't match directly with the common types, and for this reason, the package api/apitypes is used
 18to facilitate the format conversion. Most of the time, this is done directly at the db level.
 19- The API endpoints are fully documented using OpenAPI aka Swagger. All the endpoints are tested against the spec to ensure consistency
 20between implementation and specification. To get a sense of which endpoints exist and how they work, it's strongly recommended to check this specification.
 21The specification can be found at api/swagger.yml.
 22- In general, all the API endpoints produce queries to the SQL database in order to retrieve / insert the requested information. The most notable exceptions to this are
 23the /config endpoint, which returns a static object generated at construction time, and the /state, which also is retrieved from the database, but it's generated by API/stateapiupdater package.
 24*/
 25package api
 26
 27import (
 28	"errors"
 29
 30	ethCommon "github.com/ethereum/go-ethereum/common"
 31	"github.com/gin-gonic/gin"
 32	"github.com/hermeznetwork/hermez-node/db/historydb"
 33	"github.com/hermeznetwork/hermez-node/db/l2db"
 34	"github.com/hermeznetwork/hermez-node/metric"
 35	"github.com/hermeznetwork/tracerr"
 36)
 37
 38// API serves HTTP requests to allow external interaction with the Hermez node
 39type API struct {
 40	h             *historydb.HistoryDB
 41	cg            *configAPI
 42	l2            *l2db.L2DB
 43	hermezAddress ethCommon.Address
 44}
 45
 46// NewAPI sets the endpoints and the appropriate handlers, but doesn't start the server
 47func NewAPI(
 48	coordinatorEndpoints, explorerEndpoints bool,
 49	server *gin.Engine,
 50	hdb *historydb.HistoryDB,
 51	l2db *l2db.L2DB,
 52) (*API, error) {
 53	// Check input
 54	if coordinatorEndpoints && l2db == nil {
 55		return nil, tracerr.Wrap(errors.New("cannot serve Coordinator endpoints without L2DB"))
 56	}
 57	if explorerEndpoints && hdb == nil {
 58		return nil, tracerr.Wrap(errors.New("cannot serve Explorer endpoints without HistoryDB"))
 59	}
 60	consts, err := hdb.GetConstants()
 61	if err != nil {
 62		return nil, err
 63	}
 64	a := &API{
 65		h: hdb,
 66		cg: &configAPI{
 67			RollupConstants:   *newRollupConstants(consts.Rollup),
 68			AuctionConstants:  consts.Auction,
 69			WDelayerConstants: consts.WDelayer,
 70			ChainID:           consts.ChainID,
 71		},
 72		l2:            l2db,
 73		hermezAddress: consts.HermezAddress,
 74	}
 75
 76	middleware, err := metric.PrometheusMiddleware()
 77	if err != nil {
 78		return nil, err
 79	}
 80	server.Use(middleware)
 81
 82	server.NoRoute(a.noRoute)
 83
 84	v1 := server.Group("/v1")
 85
 86	// Add coordinator endpoints
 87	if coordinatorEndpoints {
 88		// Account creation authorization
 89		v1.POST("/account-creation-authorization", a.postAccountCreationAuth)
 90		v1.GET("/account-creation-authorization/:hezEthereumAddress", a.getAccountCreationAuth)
 91		// Transaction
 92		v1.POST("/transactions-pool", a.postPoolTx)
 93		v1.GET("/transactions-pool/:id", a.getPoolTx)
 94	}
 95
 96	// Add explorer endpoints
 97	if explorerEndpoints {
 98		// Account
 99		v1.GET("/accounts", a.getAccounts)
100		v1.GET("/accounts/:accountIndex", a.getAccount)
101		v1.GET("/exits", a.getExits)
102		v1.GET("/exits/:batchNum/:accountIndex", a.getExit)
103		// Transaction
104		v1.GET("/transactions-history", a.getHistoryTxs)
105		v1.GET("/transactions-history/:id", a.getHistoryTx)
106		// Batches
107		v1.GET("/batches", a.getBatches)
108		v1.GET("/batches/:batchNum", a.getBatch)
109		v1.GET("/full-batches/:batchNum", a.getFullBatch)
110		// Slots
111		v1.GET("/slots", a.getSlots)
112		v1.GET("/slots/:slotNum", a.getSlot)
113		// Bids
114		v1.GET("/bids", a.getBids)
115		// State
116		v1.GET("/state", a.getState)
117		// Config
118		v1.GET("/config", a.getConfig)
119		// Tokens
120		v1.GET("/tokens", a.getTokens)
121		v1.GET("/tokens/:id", a.getToken)
122		// Coordinators
123		v1.GET("/coordinators", a.getCoordinators)
124	}
125
126	return a, nil
127}