mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 11:26:44 +01:00
Impls exit endpoints and change pagination to cursor
This commit is contained in:
848
api/api_test.go
848
api/api_test.go
File diff suppressed because it is too large
Load Diff
@@ -7,36 +7,52 @@ import (
|
||||
|
||||
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||
"github.com/hermeznetwork/hermez-node/common"
|
||||
"github.com/hermeznetwork/hermez-node/db"
|
||||
"github.com/hermeznetwork/hermez-node/db/historydb"
|
||||
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||
"github.com/iden3/go-merkletree"
|
||||
)
|
||||
|
||||
// Commons of the API
|
||||
|
||||
type pagination struct {
|
||||
TotalItems int `json:"totalItems"`
|
||||
LastReturnedItem int `json:"lastReturnedItem"`
|
||||
}
|
||||
|
||||
//nolint:govet this is a temp patch to avoid running the test
|
||||
type paginationer interface {
|
||||
GetPagination() pagination
|
||||
Len() int
|
||||
}
|
||||
|
||||
type errorMsg struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
// History Tx related
|
||||
func bjjToString(bjj *babyjub.PublicKey) string {
|
||||
pkComp := [32]byte(bjj.Compress())
|
||||
sum := pkComp[0]
|
||||
for i := 1; i < len(pkComp); i++ {
|
||||
sum += pkComp[i]
|
||||
}
|
||||
bjjSum := append(pkComp[:], sum)
|
||||
return "hez:" + base64.RawURLEncoding.EncodeToString(bjjSum)
|
||||
}
|
||||
|
||||
func ethAddrToHez(addr ethCommon.Address) string {
|
||||
return "hez:" + addr.String()
|
||||
}
|
||||
|
||||
func idxToHez(idx common.Idx, tokenSymbol string) string {
|
||||
return "hez:" + tokenSymbol + ":" + strconv.Itoa(int(idx))
|
||||
}
|
||||
|
||||
// History Tx
|
||||
|
||||
type historyTxsAPI struct {
|
||||
Txs []historyTxAPI `json:"transactions"`
|
||||
Pagination pagination `json:"pagination"`
|
||||
Pagination *db.Pagination `json:"pagination"`
|
||||
}
|
||||
|
||||
func (htx *historyTxsAPI) GetPagination() pagination { return htx.Pagination }
|
||||
func (htx *historyTxsAPI) Len() int { return len(htx.Txs) }
|
||||
func (htx *historyTxsAPI) GetPagination() *db.Pagination {
|
||||
if htx.Txs[0].ItemID < htx.Txs[len(htx.Txs)-1].ItemID {
|
||||
htx.Pagination.FirstReturnedItem = htx.Txs[0].ItemID
|
||||
htx.Pagination.LastReturnedItem = htx.Txs[len(htx.Txs)-1].ItemID
|
||||
} else {
|
||||
htx.Pagination.LastReturnedItem = htx.Txs[0].ItemID
|
||||
htx.Pagination.FirstReturnedItem = htx.Txs[len(htx.Txs)-1].ItemID
|
||||
}
|
||||
return htx.Pagination
|
||||
}
|
||||
func (htx *historyTxsAPI) Len() int { return len(htx.Txs) }
|
||||
|
||||
type l1Info struct {
|
||||
ToForgeL1TxsNum *int64 `json:"toForgeL1TransactionsNum"`
|
||||
@@ -57,6 +73,7 @@ type l2Info struct {
|
||||
type historyTxAPI struct {
|
||||
IsL1 string `json:"L1orL2"`
|
||||
TxID string `json:"id"`
|
||||
ItemID int `json:"itemId"`
|
||||
Type common.TxType `json:"type"`
|
||||
Position int `json:"position"`
|
||||
FromIdx *string `json:"fromAccountIndex"`
|
||||
@@ -75,6 +92,7 @@ func historyTxsToAPI(dbTxs []historydb.HistoryTx) []historyTxAPI {
|
||||
for i := 0; i < len(dbTxs); i++ {
|
||||
apiTx := historyTxAPI{
|
||||
TxID: dbTxs[i].TxID.String(),
|
||||
ItemID: dbTxs[i].ItemID,
|
||||
Type: dbTxs[i].Type,
|
||||
Position: dbTxs[i].Position,
|
||||
ToIdx: idxToHez(dbTxs[i].ToIdx, dbTxs[i].TokenSymbol),
|
||||
@@ -124,20 +142,60 @@ func historyTxsToAPI(dbTxs []historydb.HistoryTx) []historyTxAPI {
|
||||
return apiTxs
|
||||
}
|
||||
|
||||
func bjjToString(bjj *babyjub.PublicKey) string {
|
||||
pkComp := [32]byte(bjj.Compress())
|
||||
sum := pkComp[0]
|
||||
for i := 1; i < len(pkComp); i++ {
|
||||
sum += pkComp[i]
|
||||
// Exit
|
||||
|
||||
type exitsAPI struct {
|
||||
Exits []exitAPI `json:"exits"`
|
||||
Pagination *db.Pagination `json:"pagination"`
|
||||
}
|
||||
|
||||
func (e *exitsAPI) GetPagination() *db.Pagination {
|
||||
if e.Exits[0].ItemID < e.Exits[len(e.Exits)-1].ItemID {
|
||||
e.Pagination.FirstReturnedItem = e.Exits[0].ItemID
|
||||
e.Pagination.LastReturnedItem = e.Exits[len(e.Exits)-1].ItemID
|
||||
} else {
|
||||
e.Pagination.LastReturnedItem = e.Exits[0].ItemID
|
||||
e.Pagination.FirstReturnedItem = e.Exits[len(e.Exits)-1].ItemID
|
||||
}
|
||||
bjjSum := append(pkComp[:], sum)
|
||||
return "hez:" + base64.RawURLEncoding.EncodeToString(bjjSum)
|
||||
return e.Pagination
|
||||
}
|
||||
func (e *exitsAPI) Len() int { return len(e.Exits) }
|
||||
|
||||
type exitAPI struct {
|
||||
ItemID int `json:"itemId"`
|
||||
BatchNum common.BatchNum `json:"batchNum"`
|
||||
AccountIdx string `json:"accountIndex"`
|
||||
MerkleProof *merkletree.CircomVerifierProof `json:"merkleProof"`
|
||||
Balance string `json:"balance"`
|
||||
InstantWithdrawn *int64 `json:"instantWithdrawn"`
|
||||
DelayedWithdrawRequest *int64 `json:"delayedWithdrawRequest"`
|
||||
DelayedWithdrawn *int64 `json:"delayedWithdrawn"`
|
||||
Token historydb.TokenRead `json:"token"`
|
||||
}
|
||||
|
||||
func ethAddrToHez(addr ethCommon.Address) string {
|
||||
return "hez:" + addr.String()
|
||||
}
|
||||
|
||||
func idxToHez(idx common.Idx, tokenSymbol string) string {
|
||||
return "hez:" + tokenSymbol + ":" + strconv.Itoa(int(idx))
|
||||
func historyExitsToAPI(dbExits []historydb.HistoryExit) []exitAPI {
|
||||
apiExits := []exitAPI{}
|
||||
for i := 0; i < len(dbExits); i++ {
|
||||
apiExits = append(apiExits, exitAPI{
|
||||
ItemID: dbExits[i].ItemID,
|
||||
BatchNum: dbExits[i].BatchNum,
|
||||
AccountIdx: idxToHez(dbExits[i].AccountIdx, dbExits[i].TokenSymbol),
|
||||
MerkleProof: dbExits[i].MerkleProof,
|
||||
Balance: dbExits[i].Balance.String(),
|
||||
InstantWithdrawn: dbExits[i].InstantWithdrawn,
|
||||
DelayedWithdrawRequest: dbExits[i].DelayedWithdrawRequest,
|
||||
DelayedWithdrawn: dbExits[i].DelayedWithdrawn,
|
||||
Token: historydb.TokenRead{
|
||||
TokenID: dbExits[i].TokenID,
|
||||
EthBlockNum: dbExits[i].TokenEthBlockNum,
|
||||
EthAddr: dbExits[i].TokenEthAddr,
|
||||
Name: dbExits[i].TokenName,
|
||||
Symbol: dbExits[i].TokenSymbol,
|
||||
Decimals: dbExits[i].TokenDecimals,
|
||||
USD: dbExits[i].TokenUSD,
|
||||
USDUpdate: dbExits[i].TokenUSDUpdate,
|
||||
},
|
||||
})
|
||||
}
|
||||
return apiExits
|
||||
}
|
||||
|
||||
137
api/handlers.go
137
api/handlers.go
@@ -2,23 +2,25 @@ package api
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/hermeznetwork/hermez-node/db/historydb"
|
||||
)
|
||||
|
||||
// maxLimit is the max permited items to be returned in paginated responses
|
||||
const maxLimit uint = 2049
|
||||
const (
|
||||
// maxLimit is the max permited items to be returned in paginated responses
|
||||
maxLimit uint = 2049
|
||||
|
||||
// dfltLast indicates how paginated endpoints use the query param last if not provided
|
||||
const dfltLast = false
|
||||
// dfltOrder indicates how paginated endpoints are ordered if not specified
|
||||
dfltOrder = historydb.OrderAsc
|
||||
|
||||
// dfltLimit indicates the limit of returned items in paginated responses if the query param limit is not provided
|
||||
const dfltLimit uint = 20
|
||||
// dfltLimit indicates the limit of returned items in paginated responses if the query param limit is not provided
|
||||
dfltLimit uint = 20
|
||||
|
||||
// 2^32 -1
|
||||
const maxUint32 = 4294967295
|
||||
// 2^32 -1
|
||||
maxUint32 = 4294967295
|
||||
)
|
||||
|
||||
func postAccountCreationAuth(c *gin.Context) {
|
||||
|
||||
@@ -45,47 +47,73 @@ func getAccount(c *gin.Context) {
|
||||
}
|
||||
|
||||
func getExits(c *gin.Context) {
|
||||
// Get query parameters
|
||||
// Account filters
|
||||
tokenID, addr, bjj, idx, err := parseAccountFilters(c)
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
}
|
||||
// BatchNum
|
||||
batchNum, err := parseQueryUint("batchNum", nil, 0, maxUint32, c)
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
}
|
||||
// Pagination
|
||||
fromItem, order, limit, err := parsePagination(c)
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
}
|
||||
|
||||
// Fetch exits from historyDB
|
||||
exits, pagination, err := h.GetExits(
|
||||
addr, bjj, tokenID, idx, batchNum, fromItem, limit, order,
|
||||
)
|
||||
if err != nil {
|
||||
retSQLErr(err, c)
|
||||
return
|
||||
}
|
||||
|
||||
// Build succesfull response
|
||||
apiExits := historyExitsToAPI(exits)
|
||||
c.JSON(http.StatusOK, &exitsAPI{
|
||||
Exits: apiExits,
|
||||
Pagination: pagination,
|
||||
})
|
||||
}
|
||||
|
||||
func getExit(c *gin.Context) {
|
||||
|
||||
// Get batchNum and accountIndex
|
||||
batchNum, err := parseParamUint("batchNum", nil, 0, maxUint32, c)
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
}
|
||||
idx, err := parseParamIdx(c)
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
}
|
||||
// Fetch tx from historyDB
|
||||
exit, err := h.GetExit(batchNum, idx)
|
||||
if err != nil {
|
||||
retSQLErr(err, c)
|
||||
return
|
||||
}
|
||||
apiExits := historyExitsToAPI([]historydb.HistoryExit{*exit})
|
||||
// Build succesfull response
|
||||
c.JSON(http.StatusOK, apiExits[0])
|
||||
}
|
||||
|
||||
func getHistoryTxs(c *gin.Context) {
|
||||
// Get query parameters
|
||||
// TokenID
|
||||
tokenID, err := parseQueryUint("tokenId", nil, 0, maxUint32, c)
|
||||
tokenID, addr, bjj, idx, err := parseAccountFilters(c)
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
}
|
||||
// Hez Eth addr
|
||||
addr, err := parseQueryHezEthAddr(c)
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
}
|
||||
// BJJ
|
||||
bjj, err := parseQueryBJJ(c)
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
}
|
||||
if addr != nil && bjj != nil {
|
||||
retBadReq(errors.New("bjj and hermezEthereumAddress params are incompatible"), c)
|
||||
return
|
||||
}
|
||||
// Idx
|
||||
idx, err := parseIdx(c)
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
}
|
||||
if idx != nil && (addr != nil || bjj != nil || tokenID != nil) {
|
||||
retBadReq(errors.New("accountIndex is incompatible with BJJ, hermezEthereumAddress and tokenId"), c)
|
||||
return
|
||||
}
|
||||
// BatchNum
|
||||
batchNum, err := parseQueryUint("batchNum", nil, 0, maxUint32, c)
|
||||
if err != nil {
|
||||
@@ -99,15 +127,15 @@ func getHistoryTxs(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
// Pagination
|
||||
offset, last, limit, err := parsePagination(c)
|
||||
fromItem, order, limit, err := parsePagination(c)
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
}
|
||||
|
||||
// Fetch txs from historyDB
|
||||
txs, totalItems, err := h.GetHistoryTxs(
|
||||
addr, bjj, tokenID, idx, batchNum, txType, offset, limit, *last,
|
||||
txs, pagination, err := h.GetHistoryTxs(
|
||||
addr, bjj, tokenID, idx, batchNum, txType, fromItem, limit, order,
|
||||
)
|
||||
if err != nil {
|
||||
retSQLErr(err, c)
|
||||
@@ -116,21 +144,28 @@ func getHistoryTxs(c *gin.Context) {
|
||||
|
||||
// Build succesfull response
|
||||
apiTxs := historyTxsToAPI(txs)
|
||||
lastRet := int(*offset) + len(apiTxs) - 1
|
||||
if *last {
|
||||
lastRet = totalItems - 1
|
||||
}
|
||||
c.JSON(http.StatusOK, &historyTxsAPI{
|
||||
Txs: apiTxs,
|
||||
Pagination: pagination{
|
||||
TotalItems: totalItems,
|
||||
LastReturnedItem: lastRet,
|
||||
},
|
||||
Txs: apiTxs,
|
||||
Pagination: pagination,
|
||||
})
|
||||
}
|
||||
|
||||
func getHistoryTx(c *gin.Context) {
|
||||
|
||||
// Get TxID
|
||||
txID, err := parseParamTxID(c)
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
}
|
||||
// Fetch tx from historyDB
|
||||
tx, err := h.GetHistoryTx(txID)
|
||||
if err != nil {
|
||||
retSQLErr(err, c)
|
||||
return
|
||||
}
|
||||
apiTxs := historyTxsToAPI([]historydb.HistoryTx{*tx})
|
||||
// Build succesfull response
|
||||
c.JSON(http.StatusOK, apiTxs[0])
|
||||
}
|
||||
|
||||
func getBatches(c *gin.Context) {
|
||||
|
||||
151
api/parsers.go
151
api/parsers.go
@@ -9,56 +9,49 @@ import (
|
||||
|
||||
ethCommon "github.com/ethereum/go-ethereum/common"
|
||||
"github.com/hermeznetwork/hermez-node/common"
|
||||
"github.com/hermeznetwork/hermez-node/db/historydb"
|
||||
"github.com/iden3/go-iden3-crypto/babyjub"
|
||||
)
|
||||
|
||||
// Query parsers
|
||||
|
||||
type querier interface {
|
||||
Query(string) string
|
||||
}
|
||||
|
||||
func parsePagination(c querier) (*uint, *bool, *uint, error) {
|
||||
// Offset
|
||||
offset := new(uint)
|
||||
*offset = 0
|
||||
offset, err := parseQueryUint("offset", offset, 0, maxUint32, c)
|
||||
func parsePagination(c querier) (fromItem *uint, order string, limit *uint, err error) {
|
||||
// FromItem
|
||||
fromItem, err = parseQueryUint("fromItem", nil, 0, maxUint32, c)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, "", nil, err
|
||||
}
|
||||
// Last
|
||||
last := new(bool)
|
||||
*last = dfltLast
|
||||
last, err = parseQueryBool("last", last, c)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
if *last && (offset != nil && *offset > 0) {
|
||||
return nil, nil, nil, errors.New(
|
||||
"last and offset are incompatible, provide only one of them",
|
||||
// Order
|
||||
order = dfltOrder
|
||||
const orderName = "order"
|
||||
orderStr := c.Query(orderName)
|
||||
if orderStr != "" && !(orderStr == historydb.OrderAsc || historydb.OrderDesc == orderStr) {
|
||||
return nil, "", nil, errors.New(
|
||||
"order must have the value " + historydb.OrderAsc + " or " + historydb.OrderDesc,
|
||||
)
|
||||
}
|
||||
if orderStr == historydb.OrderAsc {
|
||||
order = historydb.OrderAsc
|
||||
} else if orderStr == historydb.OrderDesc {
|
||||
order = historydb.OrderDesc
|
||||
}
|
||||
// Limit
|
||||
limit := new(uint)
|
||||
limit = new(uint)
|
||||
*limit = dfltLimit
|
||||
limit, err = parseQueryUint("limit", limit, 1, maxLimit, c)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
return nil, "", nil, err
|
||||
}
|
||||
return offset, last, limit, nil
|
||||
return fromItem, order, limit, nil
|
||||
}
|
||||
|
||||
func parseQueryUint(name string, dflt *uint, min, max uint, c querier) (*uint, error) { //nolint:SA4009 res may be not overwriten
|
||||
str := c.Query(name)
|
||||
if str != "" {
|
||||
resInt, err := strconv.Atoi(str)
|
||||
if err != nil || resInt < 0 || resInt < int(min) || resInt > int(max) {
|
||||
return nil, fmt.Errorf(
|
||||
"Inavlid %s. Must be an integer within the range [%d, %d]",
|
||||
name, min, max)
|
||||
}
|
||||
res := uint(resInt)
|
||||
return &res, nil
|
||||
}
|
||||
return dflt, nil
|
||||
return stringToUint(str, name, dflt, min, max)
|
||||
}
|
||||
|
||||
func parseQueryBool(name string, dflt *bool, c querier) (*bool, error) { //nolint:SA4009 res may be not overwriten
|
||||
@@ -183,19 +176,105 @@ func parseQueryTxType(c querier) (*common.TxType, error) {
|
||||
)
|
||||
}
|
||||
|
||||
func parseIdx(c querier) (*uint, error) {
|
||||
func parseIdx(c querier) (*common.Idx, error) {
|
||||
const name = "accountIndex"
|
||||
addrStr := c.Query(name)
|
||||
if addrStr == "" {
|
||||
idxStr := c.Query(name)
|
||||
return stringToIdx(idxStr, name)
|
||||
}
|
||||
|
||||
func parseAccountFilters(c querier) (*common.TokenID, *ethCommon.Address, *babyjub.PublicKey, *common.Idx, error) {
|
||||
// TokenID
|
||||
tid, err := parseQueryUint("tokenId", nil, 0, maxUint32, c)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
var tokenID *common.TokenID
|
||||
if tid != nil {
|
||||
tokenID = new(common.TokenID)
|
||||
*tokenID = common.TokenID(*tid)
|
||||
}
|
||||
// Hez Eth addr
|
||||
addr, err := parseQueryHezEthAddr(c)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
// BJJ
|
||||
bjj, err := parseQueryBJJ(c)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
if addr != nil && bjj != nil {
|
||||
return nil, nil, nil, nil,
|
||||
errors.New("bjj and hermezEthereumAddress params are incompatible")
|
||||
}
|
||||
// Idx
|
||||
idx, err := parseIdx(c)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, err
|
||||
}
|
||||
if idx != nil && (addr != nil || bjj != nil || tokenID != nil) {
|
||||
return nil, nil, nil, nil,
|
||||
errors.New("accountIndex is incompatible with BJJ, hermezEthereumAddress and tokenId")
|
||||
}
|
||||
return tokenID, addr, bjj, idx, nil
|
||||
}
|
||||
|
||||
// Param parsers
|
||||
|
||||
type paramer interface {
|
||||
Param(string) string
|
||||
}
|
||||
|
||||
func parseParamTxID(c paramer) (common.TxID, error) {
|
||||
const name = "id"
|
||||
txIDStr := c.Param(name)
|
||||
if txIDStr == "" {
|
||||
return common.TxID{}, fmt.Errorf("%s is required", name)
|
||||
}
|
||||
txID, err := common.NewTxIDFromString(txIDStr)
|
||||
if err != nil {
|
||||
return common.TxID{}, fmt.Errorf("invalid %s", name)
|
||||
}
|
||||
return txID, nil
|
||||
}
|
||||
|
||||
func parseParamIdx(c paramer) (*common.Idx, error) {
|
||||
const name = "accountIndex"
|
||||
idxStr := c.Param(name)
|
||||
return stringToIdx(idxStr, name)
|
||||
}
|
||||
|
||||
func parseParamUint(name string, dflt *uint, min, max uint, c paramer) (*uint, error) { //nolint:SA4009 res may be not overwriten
|
||||
str := c.Param(name)
|
||||
return stringToUint(str, name, dflt, min, max)
|
||||
}
|
||||
|
||||
func stringToIdx(idxStr, name string) (*common.Idx, error) {
|
||||
if idxStr == "" {
|
||||
return nil, nil
|
||||
}
|
||||
splitted := strings.Split(addrStr, ":")
|
||||
splitted := strings.Split(idxStr, ":")
|
||||
const expectedLen = 3
|
||||
if len(splitted) != expectedLen {
|
||||
if len(splitted) != expectedLen || splitted[0] != "hez" {
|
||||
return nil, fmt.Errorf(
|
||||
"invalid %s, must follow this: hez:<tokenSymbol>:index", name)
|
||||
}
|
||||
// TODO: check that the tokenSymbol match the token related to the account index
|
||||
idxInt, err := strconv.Atoi(splitted[2])
|
||||
idx := uint(idxInt)
|
||||
idx := common.Idx(idxInt)
|
||||
return &idx, err
|
||||
}
|
||||
|
||||
func stringToUint(uintStr, name string, dflt *uint, min, max uint) (*uint, error) {
|
||||
if uintStr != "" {
|
||||
resInt, err := strconv.Atoi(uintStr)
|
||||
if err != nil || resInt < 0 || resInt < int(min) || resInt > int(max) {
|
||||
return nil, fmt.Errorf(
|
||||
"Inavlid %s. Must be an integer within the range [%d, %d]",
|
||||
name, min, max)
|
||||
}
|
||||
res := uint(resInt)
|
||||
return &res, nil
|
||||
}
|
||||
return dflt, nil
|
||||
}
|
||||
|
||||
@@ -111,52 +111,46 @@ func TestParseQueryBool(t *testing.T) {
|
||||
func TestParsePagination(t *testing.T) {
|
||||
c := &queryParser{}
|
||||
c.m = make(map[string]string)
|
||||
// Offset out of range
|
||||
c.m["offset"] = "-1"
|
||||
// fromItem out of range
|
||||
c.m["fromItem"] = "-1"
|
||||
_, _, _, err := parsePagination(c)
|
||||
assert.Error(t, err)
|
||||
c.m["offset"] = strconv.Itoa(maxUint32 + 1)
|
||||
c.m["fromItem"] = strconv.Itoa(maxUint32 + 1)
|
||||
_, _, _, err = parsePagination(c)
|
||||
assert.Error(t, err)
|
||||
c.m["offset"] = ""
|
||||
// Limit out of range
|
||||
c.m["limit"] = "0"
|
||||
c.m["fromItem"] = ""
|
||||
// Bad order
|
||||
c.m["order"] = "0"
|
||||
_, _, _, err = parsePagination(c)
|
||||
assert.Error(t, err)
|
||||
c.m["limit"] = strconv.Itoa(int(maxLimit) + 1)
|
||||
_, _, _, err = parsePagination(c)
|
||||
assert.Error(t, err)
|
||||
c.m["limit"] = ""
|
||||
// Last and offset
|
||||
c.m["offset"] = "1"
|
||||
c.m["last"] = "true"
|
||||
c.m["order"] = strconv.Itoa(int(maxLimit) + 1)
|
||||
_, _, _, err = parsePagination(c)
|
||||
assert.Error(t, err)
|
||||
// Default
|
||||
c.m["offset"] = ""
|
||||
c.m["last"] = ""
|
||||
c.m["fromItem"] = ""
|
||||
c.m["order"] = ""
|
||||
c.m["limit"] = ""
|
||||
offset, last, limit, err := parsePagination(c)
|
||||
fromItem, order, limit, err := parsePagination(c)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, int(*offset))
|
||||
assert.Equal(t, dfltLast, *last)
|
||||
assert.Nil(t, fromItem)
|
||||
assert.Equal(t, dfltOrder, order)
|
||||
assert.Equal(t, dfltLimit, *limit)
|
||||
// Correct
|
||||
c.m["offset"] = ""
|
||||
c.m["last"] = "true"
|
||||
c.m["fromItem"] = ""
|
||||
c.m["order"] = "ASC"
|
||||
c.m["limit"] = "25"
|
||||
offset, last, limit, err = parsePagination(c)
|
||||
fromItem, order, limit, err = parsePagination(c)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0, int(*offset))
|
||||
assert.True(t, *last)
|
||||
assert.Nil(t, fromItem)
|
||||
assert.Equal(t, "ASC", order)
|
||||
assert.Equal(t, 25, int(*limit))
|
||||
c.m["offset"] = "25"
|
||||
c.m["last"] = "false"
|
||||
c.m["fromItem"] = "25"
|
||||
c.m["order"] = "DESC"
|
||||
c.m["limit"] = "50"
|
||||
offset, last, limit, err = parsePagination(c)
|
||||
fromItem, order, limit, err = parsePagination(c)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 25, int(*offset))
|
||||
assert.False(t, *last)
|
||||
assert.Equal(t, 25, int(*fromItem))
|
||||
assert.Equal(t, "DESC", order)
|
||||
assert.Equal(t, 50, int(*limit))
|
||||
}
|
||||
|
||||
|
||||
300
api/swagger.yml
300
api/swagger.yml
@@ -7,31 +7,27 @@ info:
|
||||
* Explorer: List transactions, slots, batches, ...
|
||||
* Exchange integrations
|
||||
|
||||
### Pagination
|
||||
|
||||
#### Usage
|
||||
|
||||
All the endpoints that return a list of undefined size use pagination. Unless the opposite is explicitly said.
|
||||
All the retunred items are ordered by ascending chronological order.
|
||||
This may not be trivial to deduce as the atributes used to order are not timestamps but the protocol ensures that those atributes follow the mentioned chronological order.
|
||||
Each endpoint description clarify this in the `offset` description.
|
||||
|
||||
The response of the calls to these endpoints will always include a `pagination` object that includes `totalItems` and `lastReturnedItem`.
|
||||
To iterate over the items the following query parameters are used:
|
||||
- `offset`: Indicates the first item that will be returned. Defaul 0. Incompatible with `last`.
|
||||
- `limit`: Indicates the maximum number of returned items. Default 20. Maximum 2049.
|
||||
- `last`: When true the last `limit` items are returned. Default false. Incompatible with `offset`.
|
||||
|
||||
Iterate items in ascending chronological order:
|
||||
|
||||
1. Call the endpoint with no `offset` nor `last`.
|
||||
2. Call the endpoint with `offset=<lastReturnedItem + 1>` until `lastReturnedItem == totalItems - 1`.
|
||||
|
||||
Iterate items in descending chronological order:
|
||||
|
||||
1. Call the endpoint with `last`.
|
||||
2. Call the endpoint with `offset=<min(0, lastReturnedItem - 2*limit)>`. Once the `calculated offset == 0`, it will be known that that call will return the first item and therefore no subsequent calls need to be done.
|
||||
If the `totalItems` change while iterating, it means that new items have been added at the end of the list. To fetch this items, use the following: `offset=<first received lastReturnedItem + 1>`, and from there iterate as decribed in *Iterate items in ascending chronological order*.
|
||||
In order to use pagination, three query parameters are used:
|
||||
* `fromItem`: indicates the first item to be returned. In general, this parameter shouldn't be provided in the first call to the endpoint, and use the `itemId` of the last returned item (+/-) 1, if the order is (ascending/descending).
|
||||
* `order`: all pginated items are ordered chronologicaly. However the specific fields to guarantee this order depend on each endpoint. For this purpose, `itemId` is used (itemId follows ascending chronological order except for unforged L1 user transactions). If the parameter is not provided, ascending order will be used by default.
|
||||
* `limit`: maximum amount of items to include in each response. Default is 20, maximum 2049.
|
||||
|
||||
**Note:** The returned list will alway be in ascending chronlogical order, so the returned arrays must be iterated from end to start in order to achieve reverse chronological order.
|
||||
|
||||
**Note:** Pagination safety can be affected by Ethereum reorgs. In most of the cases this means that the last page can be changed, but older items should be safe.
|
||||
Responses for those endpoint will always include a `pagination` object. This object includes the total amount of items that the endpoint will return at a given time with the given filters. Apart from that, it also includes the `itemId` of the last and first items that will be returned (not in a single response but within the total items). These two properties can be used to know when to stop querying.
|
||||
|
||||
#### Reorgs and safetyness
|
||||
|
||||
Since all the items are ordered chronologicaly, there are no safety problems when fetching items in ascending order, except for reorgs (more on this later).
|
||||
On the other hand, when iterating in descending order, new items will be added at the beginning. This doesn't cause any safety problem, but to get those new items, it's necessary to start queryng without the `fromItem` set to `pagination.lastItem`.
|
||||
To handle reorgs, the `itemId` can be used since it will change. This is important since other identifiers may be the same but with different content. As an example, if the batch 424 get's reorged, it will be deleted, but eventualy, a new batch 424 will appear with potentialy different content.
|
||||
|
||||
### Signatures
|
||||
|
||||
The POST endpoint require to be signed using BabyJubJub or Ethereum keys. TODO: add references to libraries / examples / ...
|
||||
|
||||
version: "0.0.1"
|
||||
title: Hermez Network API
|
||||
@@ -164,20 +160,22 @@ paths:
|
||||
type: string
|
||||
description: Comma separated list of token identifiers.
|
||||
example: "3,87,91"
|
||||
- name: offset
|
||||
- name: fromItem
|
||||
in: query
|
||||
required: false
|
||||
description: |
|
||||
- Order: accounts will be ordered by increasing account index.
|
||||
- Default first item: the first account to be returned will be the one that has the smallest account index.
|
||||
description: Indicates the desired first item (using the itemId property) to be included in the response.
|
||||
schema:
|
||||
type: number
|
||||
- name: last
|
||||
- name: order
|
||||
in: query
|
||||
required: false
|
||||
description: Get the last page.
|
||||
description: Order of the returned items. Accounts will be ordered by increasing account index.
|
||||
schema:
|
||||
type: boolean
|
||||
type: string
|
||||
default: ASC
|
||||
enum:
|
||||
- ASC
|
||||
- DESC
|
||||
- name: limit
|
||||
in: query
|
||||
required: false
|
||||
@@ -258,6 +256,12 @@ paths:
|
||||
description: Get exit information. This information is required to perform a withdraw.
|
||||
operationId: getExits
|
||||
parameters:
|
||||
- name: tokenId
|
||||
in: query
|
||||
required: false
|
||||
description: Only get exits of specific token
|
||||
schema:
|
||||
$ref: '#/components/schemas/TokenId'
|
||||
- name: hezEthereumAddress
|
||||
in: query
|
||||
description: Get exits associated to a Ethereum address. Incompatible with query `BJJ` and `accountIndex`.
|
||||
@@ -272,7 +276,7 @@ paths:
|
||||
$ref: '#/components/schemas/BJJ'
|
||||
- name: accountIndex
|
||||
in: query
|
||||
description: Get exits associated to a specific account. Incompatible with queries `hezEthereumAddress` and `BJJ`.
|
||||
description: Get exits associated to a specific account. Incompatible with queries `tokenId`, `hezEthereumAddress` and `BJJ`.
|
||||
required: false
|
||||
schema:
|
||||
$ref: '#/components/schemas/AccountIndex'
|
||||
@@ -282,20 +286,22 @@ paths:
|
||||
required: false
|
||||
schema:
|
||||
$ref: '#/components/schemas/BatchNum'
|
||||
- name: offset
|
||||
- name: fromItem
|
||||
in: query
|
||||
required: false
|
||||
description: |
|
||||
- Order: exits will be ordered by increasing (batchNum, accountIndex).
|
||||
- Default first item: the first exit to be returned will be the one that has the smallest (baychNum, accountIndex).
|
||||
description: Indicates the desired first item (using the itemId property) to be included in the response.
|
||||
schema:
|
||||
type: number
|
||||
- name: last
|
||||
- name: order
|
||||
in: query
|
||||
required: false
|
||||
description: Get the last page.
|
||||
description: Order of the returned items. Exits will be ordered by increasing (batchNum, accountIndex).
|
||||
schema:
|
||||
type: boolean
|
||||
type: string
|
||||
default: ASC
|
||||
enum:
|
||||
- ASC
|
||||
- DESC
|
||||
- name: limit
|
||||
in: query
|
||||
required: false
|
||||
@@ -459,7 +465,7 @@ paths:
|
||||
description: >-
|
||||
Get historical transactions. This endpoint will return all the different types of transactions except for:
|
||||
- Transactions that are still in the transaction pool of any coordinator. These transactions can be fetched using `GET /transactions-pool/{id}`.
|
||||
- L1 transactions that have not been forged yet. These transactions can be fetched using `GET /transactions-history/{id}`.
|
||||
- L1 transactions sent by users that have not been forged yet. These transactions can be fetched using `GET /transactions-history/{id}`.
|
||||
operationId: getHistoryTxs
|
||||
parameters:
|
||||
- name: tokenId
|
||||
@@ -498,20 +504,22 @@ paths:
|
||||
description: Only get transactions of a specific type.
|
||||
schema:
|
||||
$ref: '#/components/schemas/TransactionType'
|
||||
- name: offset
|
||||
- name: fromItem
|
||||
in: query
|
||||
required: false
|
||||
description: |
|
||||
- Order: History transactions will be ordered by increasing (batchNum, position).
|
||||
- Default first item: the first transaction to be returned will be the one that has the smallest (batchNum, position).
|
||||
description: Indicates the desired first item (using the itemId property) to be included in the response.
|
||||
schema:
|
||||
type: number
|
||||
- name: last
|
||||
- name: order
|
||||
in: query
|
||||
required: false
|
||||
description: Get the last page.
|
||||
description: Order of the returned items. History transactions will be ordered by (batchNum, position).
|
||||
schema:
|
||||
type: boolean
|
||||
type: string
|
||||
default: ASC
|
||||
enum:
|
||||
- ASC
|
||||
- DESC
|
||||
- name: limit
|
||||
in: query
|
||||
required: false
|
||||
@@ -612,20 +620,22 @@ paths:
|
||||
description: Include only batches forged by `forgerAddr`
|
||||
schema:
|
||||
$ref: '#/components/schemas/EthereumAddress'
|
||||
- name: offset
|
||||
- name: fromItem
|
||||
in: query
|
||||
required: false
|
||||
description: |
|
||||
- Order: batches will be ordered by increasing `batchNum`.
|
||||
- Default first item: the first batch to be returned will be the one that has the smallest `batchNum`.
|
||||
description: Indicates the desired first item (using the itemId property) to be included in the response.
|
||||
schema:
|
||||
type: number
|
||||
- name: last
|
||||
- name: order
|
||||
in: query
|
||||
required: false
|
||||
description: Get the last page.
|
||||
description: Order of the returned items. Batches will be ordered by increasing `batchNum`.
|
||||
schema:
|
||||
type: boolean
|
||||
type: string
|
||||
default: ASC
|
||||
enum:
|
||||
- ASC
|
||||
- DESC
|
||||
- name: limit
|
||||
in: query
|
||||
required: false
|
||||
@@ -773,20 +783,22 @@ paths:
|
||||
description: If set to true, only include slots whose auction has finished.
|
||||
schema:
|
||||
type: boolean
|
||||
- name: offset
|
||||
- name: fromItem
|
||||
in: query
|
||||
required: false
|
||||
description: |
|
||||
- Order: slots will be ordered by increasing `slotNum`.
|
||||
- Default first item: the first slot to be returned will be the one that has the smallest `slotNum`.
|
||||
description: Indicates the desired first item (using the itemId property) to be included in the response.
|
||||
schema:
|
||||
type: number
|
||||
- name: last
|
||||
- name: order
|
||||
in: query
|
||||
required: false
|
||||
description: Get the last page.
|
||||
description: Order of the returned items. Slots will be ordered by increasing `slotNum`.
|
||||
schema:
|
||||
type: boolean
|
||||
type: string
|
||||
default: ASC
|
||||
enum:
|
||||
- ASC
|
||||
- DESC
|
||||
- name: limit
|
||||
in: query
|
||||
required: false
|
||||
@@ -880,20 +892,22 @@ paths:
|
||||
required: false
|
||||
schema:
|
||||
$ref: '#/components/schemas/EthereumAddress'
|
||||
- name: offset
|
||||
- name: fromItem
|
||||
in: query
|
||||
required: false
|
||||
description: |
|
||||
- Order: bids will be ordered by increasing (slotNum, bidValue)`.
|
||||
- Default first item: the first bid to be returned will be the one that has the smallest (slotNum, bidValue).
|
||||
description: Indicates the desired first item (using the itemId property) to be included in the response.
|
||||
schema:
|
||||
type: number
|
||||
- name: last
|
||||
- name: order
|
||||
in: query
|
||||
required: false
|
||||
description: Get the last page.
|
||||
description: Order of the returned items. Bids will be ordered by increasing (slotNum, bidValue)`.
|
||||
schema:
|
||||
type: boolean
|
||||
type: string
|
||||
default: ASC
|
||||
enum:
|
||||
- ASC
|
||||
- DESC
|
||||
- name: limit
|
||||
in: query
|
||||
required: false
|
||||
@@ -1031,20 +1045,22 @@ paths:
|
||||
description: Include token(s) by their names (or a substring of the name).
|
||||
schema:
|
||||
type: string
|
||||
- name: offset
|
||||
- name: fromItem
|
||||
in: query
|
||||
required: false
|
||||
description: |
|
||||
- Order: tokens will be ordered by increasing tokenID.
|
||||
- Default first item: the first token to be returned will be the one that has the smallest tokenID.
|
||||
description: Indicates the desired first item (using the itemId property) to be included in the response.
|
||||
schema:
|
||||
type: number
|
||||
- name: last
|
||||
- name: order
|
||||
in: query
|
||||
required: false
|
||||
description: Get the last page.
|
||||
description: Order of the returned items. Tokens will be ordered by increasing tokenID.
|
||||
schema:
|
||||
type: boolean
|
||||
type: string
|
||||
default: ASC
|
||||
enum:
|
||||
- ASC
|
||||
- DESC
|
||||
- name: limit
|
||||
in: query
|
||||
required: false
|
||||
@@ -1146,20 +1162,22 @@ paths:
|
||||
description: Get information about coordinators.
|
||||
operationId: getCoordinators
|
||||
parameters:
|
||||
- name: offset
|
||||
- name: fromItem
|
||||
in: query
|
||||
required: false
|
||||
description: |
|
||||
- Order: coordinators will be ordered by increasing (ethereumBlock, forgerAddr).
|
||||
- Default first item: the first token to be returned will be the one that has the smallest (ethereumBlock, forgerAddr).
|
||||
description: Indicates the desired first item (using the itemId property) to be included in the response.
|
||||
schema:
|
||||
type: number
|
||||
- name: last
|
||||
- name: order
|
||||
in: query
|
||||
required: false
|
||||
description: Get the last page.
|
||||
description: Order of the returned items. Coordinators will be ordered by increasing (ethereumBlock, forgerAddr).
|
||||
schema:
|
||||
type: boolean
|
||||
type: string
|
||||
default: ASC
|
||||
enum:
|
||||
- ASC
|
||||
- DESC
|
||||
- name: limit
|
||||
in: query
|
||||
required: false
|
||||
@@ -1228,13 +1246,16 @@ paths:
|
||||
$ref: '#/components/schemas/Error500'
|
||||
components:
|
||||
schemas:
|
||||
ItemId:
|
||||
type: integer
|
||||
description: Position of the item in the DB. This is useful for pagination, but has nothing to do with the protocol.
|
||||
PostPoolL2Transaction:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
$ref: '#/components/schemas/TransactionId'
|
||||
type:
|
||||
$ref: '#/components/schemas/TransactionType'
|
||||
$ref: '#/components/schemas/TransactionTypeL2'
|
||||
tokenId:
|
||||
$ref: '#/components/schemas/TokenId'
|
||||
fromAccountIndex:
|
||||
@@ -1341,7 +1362,7 @@ components:
|
||||
id:
|
||||
$ref: '#/components/schemas/TransactionId'
|
||||
type:
|
||||
$ref: '#/components/schemas/TransactionType'
|
||||
$ref: '#/components/schemas/TransactionTypeL2'
|
||||
fromAccountIndex:
|
||||
$ref: '#/components/schemas/AccountIndex'
|
||||
toAccountIndex:
|
||||
@@ -1480,6 +1501,14 @@ components:
|
||||
- ForceExit
|
||||
- TransferToEthAddr
|
||||
- TransferToBJJ
|
||||
TransactionTypeL2:
|
||||
type: string
|
||||
description: Type of transaction.
|
||||
enum:
|
||||
- Exit
|
||||
- Transfer
|
||||
- TransferToEthAddr
|
||||
- TransferToBJJ
|
||||
TokenId:
|
||||
type: integer
|
||||
description: Identifier of a token registered in the network.
|
||||
@@ -1556,6 +1585,8 @@ components:
|
||||
- L2
|
||||
id:
|
||||
$ref: '#/components/schemas/TransactionId'
|
||||
itemId:
|
||||
$ref: '#/components/schemas/ItemId'
|
||||
type:
|
||||
$ref: '#/components/schemas/TransactionType'
|
||||
position:
|
||||
@@ -1655,6 +1686,7 @@ components:
|
||||
required:
|
||||
- L1orL2
|
||||
- id
|
||||
- itemId
|
||||
- type
|
||||
- position
|
||||
- fromAccountIndex
|
||||
@@ -1943,29 +1975,87 @@ components:
|
||||
- example: 7394
|
||||
accountIndex:
|
||||
$ref: '#/components/schemas/AccountIndex'
|
||||
itemId:
|
||||
$ref: '#/components/schemas/ItemId'
|
||||
merkleProof:
|
||||
type: string
|
||||
type: object
|
||||
description: Existence proof of a leaf in a given Merkle Root. Encoded as hexadecimal string.
|
||||
example: "0x347089321de8971320489793a823470918fffeab"
|
||||
properties:
|
||||
Root:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
Siblings:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
OldKey:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
OldValue:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
IsOld0:
|
||||
type: boolean
|
||||
Key:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
Value:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
Fnc:
|
||||
type: integer
|
||||
required:
|
||||
- Root
|
||||
- Siblings
|
||||
- OldKey
|
||||
- OldValue
|
||||
- IsOld0
|
||||
- Key
|
||||
- Value
|
||||
- Fnc
|
||||
additionalProperties: false
|
||||
example: {"Root":[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"Siblings":[0,1,2],"OldKey":[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"OldValue":[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"IsOld0":true,"Key":[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"Value":[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"Fnc":0}
|
||||
balance:
|
||||
$ref: '#/components/schemas/BigInt'
|
||||
instantWithdrawn:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/EthBlockNum'
|
||||
- description: Block in which the exit balance was instantly withdrawn. Null indicates that an instant withdrawn hasn't been performed.
|
||||
- example: 74747363
|
||||
type: integer
|
||||
description: Block in which the exit balance was instantly withdrawn. Null indicates that an instant withdrawn hasn't been performed.
|
||||
minimum: 0
|
||||
maximum: 1.84467440737096e+19
|
||||
example: 74747363
|
||||
nullable: true
|
||||
delayedWithdrawRequest:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/EthBlockNum'
|
||||
- description: Block in which the exit balance was requested to delay withdraw. Null indicates that a delay withdraw hasn't been performed.
|
||||
- example: null
|
||||
type: integer
|
||||
description: Block in which the exit balance was requested to delay withdraw. Null indicates that a delay withdraw hasn't been performed.
|
||||
minimum: 0
|
||||
maximum: 1.84467440737096e+19
|
||||
example: null
|
||||
nullable: true
|
||||
delayedWithdrawn:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/EthBlockNum'
|
||||
- description: Block in which the exit balance was delayed withdrawn after a delay withdraw request. Null indicates that a delay withdraw hasn't been performed.
|
||||
- example: null
|
||||
type: integer
|
||||
description: Block in which the exit balance was delayed withdrawn after a delay withdraw request. Null indicates that a delay withdraw hasn't been performed.
|
||||
minimum: 0
|
||||
maximum: 1.84467440737096e+19
|
||||
example: null
|
||||
nullable: true
|
||||
token:
|
||||
$ref: '#/components/schemas/Token'
|
||||
required:
|
||||
- batchNum
|
||||
- accountIndex
|
||||
- itemId
|
||||
- merkleProof
|
||||
- balance
|
||||
- instantWithdrawn
|
||||
- delayedWithdrawRequest
|
||||
- delayedWithdrawn
|
||||
- token
|
||||
additionalProperties: false
|
||||
Exits:
|
||||
type: object
|
||||
properties:
|
||||
@@ -1975,7 +2065,11 @@ components:
|
||||
items:
|
||||
$ref: '#/components/schemas/Exit'
|
||||
pagination:
|
||||
$ref: '#/components/schemas/PaginationInfo'
|
||||
$ref: '#/components/schemas/PaginationInfo'
|
||||
required:
|
||||
- exits
|
||||
- pagination
|
||||
additionalProperties: false
|
||||
Account:
|
||||
type: object
|
||||
description: State tree leaf. It contains balance and nonce of an account.
|
||||
@@ -2217,10 +2311,14 @@ components:
|
||||
type: integer
|
||||
description: Amount of items that the endpoint can return given the filters and the current state of the database.
|
||||
example: 2048
|
||||
lastReturnedItem:
|
||||
firstItem:
|
||||
type: integer
|
||||
description: Index of the last returned item. Useful to query next items.
|
||||
example: 439
|
||||
description: The smallest itemId that the endpoint will return with the given filters.
|
||||
example: 50
|
||||
lastItem:
|
||||
type: integer
|
||||
description: The greatest itemId that the endpoint will return with the given filters.
|
||||
example: 2130
|
||||
Config:
|
||||
type: object
|
||||
description: Configuration parameters of the different smart contracts that power the Hermez network.
|
||||
|
||||
Reference in New Issue
Block a user