|
@ -1,3 +1,27 @@ |
|
|
|
|
|
/* |
|
|
|
|
|
Package api implements the public interface of the hermez-node using a HTTP REST API. |
|
|
|
|
|
There are two subsets of endpoints: |
|
|
|
|
|
- coordinatorEndpoints: used to receive L2 transactions and account creation authorizations. Targeted for wallets. |
|
|
|
|
|
- explorerEndpoints: used to provide all sorts of information about the network. Targeted for explorers and similar services. |
|
|
|
|
|
|
|
|
|
|
|
About the configuration of the API: |
|
|
|
|
|
- The API is supposed to be launched using the cli found at the package cli/node, and configured through the configuration file. |
|
|
|
|
|
- The mentioned configuration file allows exposing any combination of the endpoint subsets. |
|
|
|
|
|
- Although the API can run in a "standalone" manner using the serveapi command, it won't work properly |
|
|
|
|
|
unless another process acting as a coord or sync is filling the HistoryDB. |
|
|
|
|
|
|
|
|
|
|
|
Design principles and considerations: |
|
|
|
|
|
- In order to decouple the API process from the rest of the node, all the communication between this package and the rest of |
|
|
|
|
|
the system is done through the SQL database. As a matter of fact, the only public function of the package is the constructor NewAPI. |
|
|
|
|
|
All the information needed for the API to work should be obtained through the configuration file of the cli or the database. |
|
|
|
|
|
- The format of the requests / responses doesn't match directly with the common types, and for this reason, the package api/apitypes is used |
|
|
|
|
|
to facilitate the format conversion. Most of the time, this is done directly at the db level. |
|
|
|
|
|
- The API endpoints are fully documented using OpenAPI aka Swagger. All the endpoints are tested against the spec to ensure consistency |
|
|
|
|
|
between implementation and specification. To get a sense of which endpoints exist and how they work, it's strongly recommended to check this specification. |
|
|
|
|
|
The specification can be found at api/swagger.yml. |
|
|
|
|
|
- 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 |
|
|
|
|
|
the /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. |
|
|
|
|
|
*/ |
|
|
package api |
|
|
package api |
|
|
|
|
|
|
|
|
import ( |
|
|
import ( |
|
@ -27,7 +51,6 @@ func NewAPI( |
|
|
l2db *l2db.L2DB, |
|
|
l2db *l2db.L2DB, |
|
|
) (*API, error) { |
|
|
) (*API, error) { |
|
|
// Check input
|
|
|
// Check input
|
|
|
// TODO: is stateDB only needed for explorer endpoints or for both?
|
|
|
|
|
|
if coordinatorEndpoints && l2db == nil { |
|
|
if coordinatorEndpoints && l2db == nil { |
|
|
return nil, tracerr.Wrap(errors.New("cannot serve Coordinator endpoints without L2DB")) |
|
|
return nil, tracerr.Wrap(errors.New("cannot serve Coordinator endpoints without L2DB")) |
|
|
} |
|
|
} |
|
@ -54,7 +77,7 @@ func NewAPI( |
|
|
|
|
|
|
|
|
// Add coordinator endpoints
|
|
|
// Add coordinator endpoints
|
|
|
if coordinatorEndpoints { |
|
|
if coordinatorEndpoints { |
|
|
// Account
|
|
|
|
|
|
|
|
|
// Account creation authorization
|
|
|
v1.POST("/account-creation-authorization", a.postAccountCreationAuth) |
|
|
v1.POST("/account-creation-authorization", a.postAccountCreationAuth) |
|
|
v1.GET("/account-creation-authorization/:hezEthereumAddress", a.getAccountCreationAuth) |
|
|
v1.GET("/account-creation-authorization/:hezEthereumAddress", a.getAccountCreationAuth) |
|
|
// Transaction
|
|
|
// Transaction
|
|
@ -72,17 +95,23 @@ func NewAPI( |
|
|
// Transaction
|
|
|
// Transaction
|
|
|
v1.GET("/transactions-history", a.getHistoryTxs) |
|
|
v1.GET("/transactions-history", a.getHistoryTxs) |
|
|
v1.GET("/transactions-history/:id", a.getHistoryTx) |
|
|
v1.GET("/transactions-history/:id", a.getHistoryTx) |
|
|
// Status
|
|
|
|
|
|
|
|
|
// Batches
|
|
|
v1.GET("/batches", a.getBatches) |
|
|
v1.GET("/batches", a.getBatches) |
|
|
v1.GET("/batches/:batchNum", a.getBatch) |
|
|
v1.GET("/batches/:batchNum", a.getBatch) |
|
|
v1.GET("/full-batches/:batchNum", a.getFullBatch) |
|
|
v1.GET("/full-batches/:batchNum", a.getFullBatch) |
|
|
|
|
|
// Slots
|
|
|
v1.GET("/slots", a.getSlots) |
|
|
v1.GET("/slots", a.getSlots) |
|
|
v1.GET("/slots/:slotNum", a.getSlot) |
|
|
v1.GET("/slots/:slotNum", a.getSlot) |
|
|
|
|
|
// Bids
|
|
|
v1.GET("/bids", a.getBids) |
|
|
v1.GET("/bids", a.getBids) |
|
|
|
|
|
// State
|
|
|
v1.GET("/state", a.getState) |
|
|
v1.GET("/state", a.getState) |
|
|
|
|
|
// Config
|
|
|
v1.GET("/config", a.getConfig) |
|
|
v1.GET("/config", a.getConfig) |
|
|
|
|
|
// Tokens
|
|
|
v1.GET("/tokens", a.getTokens) |
|
|
v1.GET("/tokens", a.getTokens) |
|
|
v1.GET("/tokens/:id", a.getToken) |
|
|
v1.GET("/tokens/:id", a.getToken) |
|
|
|
|
|
// Coordinators
|
|
|
v1.GET("/coordinators", a.getCoordinators) |
|
|
v1.GET("/coordinators", a.getCoordinators) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|