hermez-node/api/handlers.go
api/handlers.goRaw
1package api
2
3import (
4 "database/sql"
5 "errors"
6 "net/http"
7
8 "github.com/gin-gonic/gin"
9 "github.com/hermeznetwork/hermez-node/common"
10 "github.com/hermeznetwork/hermez-node/db/historydb"
11)
12
13const (
14 // maxLimit is the max permited items to be returned in paginated responses
15 maxLimit uint = 2049
16
17 // dfltOrder indicates how paginated endpoints are ordered if not specified
18 dfltOrder = historydb.OrderAsc
19
20 // dfltLimit indicates the limit of returned items in paginated responses if the query param limit is not provided
21 dfltLimit uint = 20
22
23 // 2^32 -1
24 maxUint32 = 4294967295
25)
26
27var (
28 // ErrNillBidderAddr is used when a nil bidderAddr is received in the getCoordinator method
29 ErrNillBidderAddr = errors.New("biderAddr can not be nil")
30)
31
32func postAccountCreationAuth(c *gin.Context) {
33 // Parse body
34 var apiAuth accountCreationAuthAPI
35 if err := c.ShouldBindJSON(&apiAuth); err != nil {
36 retBadReq(err, c)
37 return
38 }
39 // API to common + verify signature
40 dbAuth, err := accountCreationAuthAPIToCommon(&apiAuth)
41 if err != nil {
42 retBadReq(err, c)
43 return
44 }
45 // Insert to DB
46 if err := l2.AddAccountCreationAuth(dbAuth); err != nil {
47 retSQLErr(err, c)
48 return
49 }
50 // Return OK
51 c.Status(http.StatusOK)
52}
53
54func getAccountCreationAuth(c *gin.Context) {
55 // Get hezEthereumAddress
56 addr, err := parseParamHezEthAddr(c)
57 if err != nil {
58 retBadReq(err, c)
59 return
60 }
61 // Fetch auth from l2DB
62 dbAuth, err := l2.GetAccountCreationAuth(*addr)
63 if err != nil {
64 retSQLErr(err, c)
65 return
66 }
67 apiAuth := accountCreationAuthToAPI(dbAuth)
68 // Build succesfull response
69 c.JSON(http.StatusOK, apiAuth)
70}
71
72func postPoolTx(c *gin.Context) {
73 // Parse body
74 var receivedTx receivedPoolTx
75 if err := c.ShouldBindJSON(&receivedTx); err != nil {
76 retBadReq(err, c)
77 return
78 }
79 // Transform from received to insert format and validate
80 writeTx, err := receivedTx.toDBWritePoolL2Tx()
81 if err != nil {
82 retBadReq(err, c)
83 return
84 }
85 // Insert to DB
86 if err := l2.AddTx(writeTx); err != nil {
87 retSQLErr(err, c)
88 return
89 }
90 // Return TxID
91 c.JSON(http.StatusOK, writeTx.TxID.String())
92}
93
94func getPoolTx(c *gin.Context) {
95 // Get TxID
96 txID, err := parseParamTxID(c)
97 if err != nil {
98 retBadReq(err, c)
99 return
100 }
101 // Fetch tx from l2DB
102 dbTx, err := l2.GetTx(txID)
103 if err != nil {
104 retSQLErr(err, c)
105 return
106 }
107 apiTx := poolL2TxReadToSend(dbTx)
108 // Build succesfull response
109 c.JSON(http.StatusOK, apiTx)
110}
111
112func getAccounts(c *gin.Context) {
113
114}
115
116func getAccount(c *gin.Context) {
117
118}
119
120func getExits(c *gin.Context) {
121 // Get query parameters
122 // Account filters
123 tokenID, addr, bjj, idx, err := parseAccountFilters(c)
124 if err != nil {
125 retBadReq(err, c)
126 return
127 }
128 // BatchNum
129 batchNum, err := parseQueryUint("batchNum", nil, 0, maxUint32, c)
130 if err != nil {
131 retBadReq(err, c)
132 return
133 }
134 // Pagination
135 fromItem, order, limit, err := parsePagination(c)
136 if err != nil {
137 retBadReq(err, c)
138 return
139 }
140
141 // Fetch exits from historyDB
142 exits, pagination, err := h.GetExits(
143 addr, bjj, tokenID, idx, batchNum, fromItem, limit, order,
144 )
145 if err != nil {
146 retSQLErr(err, c)
147 return
148 }
149
150 // Build succesfull response
151 apiExits := historyExitsToAPI(exits)
152 c.JSON(http.StatusOK, &exitsAPI{
153 Exits: apiExits,
154 Pagination: pagination,
155 })
156}
157
158func getExit(c *gin.Context) {
159 // Get batchNum and accountIndex
160 batchNum, err := parseParamUint("batchNum", nil, 0, maxUint32, c)
161 if err != nil {
162 retBadReq(err, c)
163 return
164 }
165 idx, err := parseParamIdx(c)
166 if err != nil {
167 retBadReq(err, c)
168 return
169 }
170 // Fetch tx from historyDB
171 exit, err := h.GetExit(batchNum, idx)
172 if err != nil {
173 retSQLErr(err, c)
174 return
175 }
176 apiExits := historyExitsToAPI([]historydb.HistoryExit{*exit})
177 // Build succesfull response
178 c.JSON(http.StatusOK, apiExits[0])
179}
180
181func getHistoryTxs(c *gin.Context) {
182 // Get query parameters
183 tokenID, addr, bjj, idx, err := parseAccountFilters(c)
184 if err != nil {
185 retBadReq(err, c)
186 return
187 }
188 // BatchNum
189 batchNum, err := parseQueryUint("batchNum", nil, 0, maxUint32, c)
190 if err != nil {
191 retBadReq(err, c)
192 return
193 }
194 // TxType
195 txType, err := parseQueryTxType(c)
196 if err != nil {
197 retBadReq(err, c)
198 return
199 }
200 // Pagination
201 fromItem, order, limit, err := parsePagination(c)
202 if err != nil {
203 retBadReq(err, c)
204 return
205 }
206
207 // Fetch txs from historyDB
208 txs, pagination, err := h.GetHistoryTxs(
209 addr, bjj, tokenID, idx, batchNum, txType, fromItem, limit, order,
210 )
211 if err != nil {
212 retSQLErr(err, c)
213 return
214 }
215
216 // Build succesfull response
217 apiTxs := historyTxsToAPI(txs)
218 c.JSON(http.StatusOK, &historyTxsAPI{
219 Txs: apiTxs,
220 Pagination: pagination,
221 })
222}
223
224func getHistoryTx(c *gin.Context) {
225 // Get TxID
226 txID, err := parseParamTxID(c)
227 if err != nil {
228 retBadReq(err, c)
229 return
230 }
231 // Fetch tx from historyDB
232 tx, err := h.GetHistoryTx(txID)
233 if err != nil {
234 retSQLErr(err, c)
235 return
236 }
237 apiTxs := historyTxsToAPI([]historydb.HistoryTx{*tx})
238 // Build succesfull response
239 c.JSON(http.StatusOK, apiTxs[0])
240}
241
242func getBatches(c *gin.Context) {
243
244}
245
246func getBatch(c *gin.Context) {
247
248}
249
250func getFullBatch(c *gin.Context) {
251
252}
253
254func getSlots(c *gin.Context) {
255
256}
257
258func getBids(c *gin.Context) {
259
260}
261
262func getNextForgers(c *gin.Context) {
263
264}
265
266func getState(c *gin.Context) {
267
268}
269
270func getConfig(c *gin.Context) {
271 c.JSON(http.StatusOK, cg)
272}
273
274func getTokens(c *gin.Context) {
275 // Account filters
276 tokenIDs, symbols, name, err := parseTokenFilters(c)
277 if err != nil {
278 retBadReq(err, c)
279 return
280 }
281 // Pagination
282 fromItem, order, limit, err := parsePagination(c)
283 if err != nil {
284 retBadReq(err, c)
285 return
286 }
287 // Fetch exits from historyDB
288 tokens, pagination, err := h.GetTokens(
289 tokenIDs, symbols, name, fromItem, limit, order,
290 )
291 if err != nil {
292 retSQLErr(err, c)
293 return
294 }
295
296 // Build succesfull response
297 apiTokens := tokensToAPI(tokens)
298 c.JSON(http.StatusOK, &tokensAPI{
299 Tokens: apiTokens,
300 Pagination: pagination,
301 })
302}
303
304func getToken(c *gin.Context) {
305 // Get TokenID
306 tokenIDUint, err := parseParamUint("id", nil, 0, maxUint32, c)
307 if err != nil {
308 retBadReq(err, c)
309 return
310 }
311 tokenID := common.TokenID(*tokenIDUint)
312 // Fetch token from historyDB
313 token, err := h.GetToken(tokenID)
314 if err != nil {
315 retSQLErr(err, c)
316 return
317 }
318 apiToken := tokensToAPI([]historydb.TokenRead{*token})
319 c.JSON(http.StatusOK, apiToken[0])
320}
321
322func getRecommendedFee(c *gin.Context) {
323
324}
325
326func getCoordinators(c *gin.Context) {
327 // Pagination
328 fromItem, order, limit, err := parsePagination(c)
329 if err != nil {
330 retBadReq(err, c)
331 return
332 }
333
334 // Fetch coordinators from historyDB
335 coordinators, pagination, err := h.GetCoordinators(fromItem, limit, order)
336 if err != nil {
337 retSQLErr(err, c)
338 return
339 }
340
341 // Build succesfull response
342 apiCoordinators := coordinatorsToAPI(coordinators)
343 c.JSON(http.StatusOK, &coordinatorsAPI{
344 Coordinators: apiCoordinators,
345 Pagination: pagination,
346 })
347}
348
349func getCoordinator(c *gin.Context) {
350 // Get bidderAddr
351 const name = "bidderAddr"
352 bidderAddr, err := parseEthAddr(c, name)
353
354 if err != nil {
355 retBadReq(err, c)
356 return
357 } else if bidderAddr == nil {
358 retBadReq(ErrNillBidderAddr, c)
359 return
360 }
361
362 coordinator, err := h.GetCoordinator(*bidderAddr)
363 if err != nil {
364 retSQLErr(err, c)
365 return
366 }
367
368 apiCoordinator := coordinatorsToAPI([]historydb.HistoryCoordinator{*coordinator})
369 c.JSON(http.StatusOK, apiCoordinator[0])
370}
371
372func retSQLErr(err error, c *gin.Context) {
373 if err == sql.ErrNoRows {
374 c.JSON(http.StatusNotFound, errorMsg{
375 Message: err.Error(),
376 })
377 } else {
378 c.JSON(http.StatusInternalServerError, errorMsg{
379 Message: err.Error(),
380 })
381 }
382}
383
384func retBadReq(err error, c *gin.Context) {
385 c.JSON(http.StatusBadRequest, errorMsg{
386 Message: err.Error(),
387 })
388}