mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
implemented get pool txs endpoint
This commit is contained in:
@@ -60,6 +60,7 @@ func NewAPI(
|
||||
// Transaction
|
||||
v1.POST("/transactions-pool", a.postPoolTx)
|
||||
v1.GET("/transactions-pool/:id", a.getPoolTx)
|
||||
v1.GET("/transactions-pool", a.getPoolTxs)
|
||||
}
|
||||
|
||||
// Add explorer endpoints
|
||||
|
||||
@@ -96,6 +96,32 @@ func parseQueryBJJ(c querier) (*babyjub.PublicKeyComp, error) {
|
||||
return hezStringToBJJ(bjjStr, name)
|
||||
}
|
||||
|
||||
func parseQueryPoolL2TxState(c querier) (*common.PoolL2TxState, error) {
|
||||
const name = "state"
|
||||
stateStr := c.Query(name)
|
||||
if stateStr == "" {
|
||||
return nil, nil
|
||||
}
|
||||
switch common.PoolL2TxState(stateStr) {
|
||||
case common.PoolL2TxStatePending:
|
||||
ret := common.PoolL2TxStatePending
|
||||
return &ret, nil
|
||||
case common.PoolL2TxStateForged:
|
||||
ret := common.PoolL2TxStateForged
|
||||
return &ret, nil
|
||||
case common.PoolL2TxStateForging:
|
||||
ret := common.PoolL2TxStateForging
|
||||
return &ret, nil
|
||||
case common.PoolL2TxStateInvalid:
|
||||
ret := common.PoolL2TxStateInvalid
|
||||
return &ret, nil
|
||||
}
|
||||
return nil, tracerr.Wrap(fmt.Errorf(
|
||||
"invalid %s, %s is not a valid option. Check the valid options in the docmentation",
|
||||
name, stateStr,
|
||||
))
|
||||
}
|
||||
|
||||
func parseQueryTxType(c querier) (*common.TxType, error) {
|
||||
const name = "type"
|
||||
typeStr := c.Query(name)
|
||||
|
||||
@@ -415,6 +415,49 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error500'
|
||||
get:
|
||||
tags:
|
||||
- Coordinator
|
||||
summary: Get transactions that are in the pool.
|
||||
operationId: getPoolTxs
|
||||
parameters:
|
||||
- name: state
|
||||
in: query
|
||||
required: false
|
||||
description: State of the transactions, e.g. "pend"
|
||||
schema:
|
||||
$ref: '#/components/schemas/PoolL2TransactionState'
|
||||
- name: accountIndex
|
||||
in: query
|
||||
required: false
|
||||
description: Id of the account
|
||||
schema:
|
||||
$ref: '#/components/schemas/AccountIndex'
|
||||
responses:
|
||||
'200':
|
||||
description: Successful operation.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PoolL2Transactions'
|
||||
'400':
|
||||
description: Bad request.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error400'
|
||||
'404':
|
||||
description: Not found.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error404'
|
||||
'500':
|
||||
description: Internal server error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error500'
|
||||
'/transactions-pool/{id}':
|
||||
get:
|
||||
tags:
|
||||
@@ -1439,6 +1482,14 @@ components:
|
||||
- requestFee
|
||||
- requestNonce
|
||||
- token
|
||||
PoolL2Transactions:
|
||||
type: object
|
||||
properties:
|
||||
transactions:
|
||||
type: array
|
||||
description: List of pool l2 transactions
|
||||
items:
|
||||
$ref: '#/components/schemas/PoolL2Transaction'
|
||||
TransactionId:
|
||||
type: string
|
||||
description: Identifier for transactions. Used for any kind of transaction (both L1 and L2). More info on how the identifiers are built [here](https://idocs.hermez.io/#/spec/architecture/db/README?id=txid)
|
||||
|
||||
@@ -55,6 +55,35 @@ func (a *API) getPoolTx(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, tx)
|
||||
}
|
||||
|
||||
func (a *API) getPoolTxs(c *gin.Context) {
|
||||
// Get idx
|
||||
idx, err := parseIdx(c)
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
}
|
||||
// Get state
|
||||
state, err := parseQueryPoolL2TxState(c)
|
||||
if err != nil {
|
||||
retBadReq(err, c)
|
||||
return
|
||||
}
|
||||
// Fetch txs from l2DB
|
||||
txs, err := a.l2.GetPoolTxs(idx, state)
|
||||
if err != nil {
|
||||
retSQLErr(err, c)
|
||||
return
|
||||
}
|
||||
|
||||
// Build successful response
|
||||
type txsResponse struct {
|
||||
Txs []*l2db.PoolTxAPI `json:"transactions"`
|
||||
}
|
||||
c.JSON(http.StatusOK, &txsResponse{
|
||||
Txs: txs,
|
||||
})
|
||||
}
|
||||
|
||||
type receivedPoolTx struct {
|
||||
TxID common.TxID `json:"id" binding:"required"`
|
||||
Type common.TxType `json:"type" binding:"required"`
|
||||
|
||||
@@ -47,6 +47,10 @@ type testPoolTxReceive struct {
|
||||
Token historydb.TokenWithUSD `json:"token"`
|
||||
}
|
||||
|
||||
type testPoolTxsResponse struct {
|
||||
Txs []testPoolTxReceive `json:"transactions"`
|
||||
}
|
||||
|
||||
// testPoolTxSend is a struct to be used as a JSON body
|
||||
// when testing POST /transactions-pool
|
||||
type testPoolTxSend struct {
|
||||
@@ -224,6 +228,25 @@ func TestPoolTxs(t *testing.T) {
|
||||
jsonTxReader = bytes.NewReader(jsonTxBytes)
|
||||
err = doBadReq("POST", endpoint, jsonTxReader, 400)
|
||||
require.NoError(t, err)
|
||||
// GET
|
||||
// get by idx
|
||||
fetchedTxs := testPoolTxsResponse{}
|
||||
require.NoError(t, doGoodReq(
|
||||
"GET",
|
||||
endpoint+"?accountIndex=hez:ETH:263",
|
||||
nil, &fetchedTxs))
|
||||
assert.Equal(t, 1, len(fetchedTxs.Txs))
|
||||
assert.Equal(t, "hez:ETH:263", fetchedTxs.Txs[0].FromIdx)
|
||||
// get by state
|
||||
require.NoError(t, doGoodReq(
|
||||
"GET",
|
||||
endpoint+"?state=pend",
|
||||
nil, &fetchedTxs))
|
||||
assert.Equal(t, 4, len(fetchedTxs.Txs))
|
||||
for _, v := range fetchedTxs.Txs {
|
||||
assert.Equal(t, common.PoolL2TxStatePending, v.State)
|
||||
}
|
||||
|
||||
// GET
|
||||
endpoint += "/"
|
||||
for _, tx := range tc.poolTxsToReceive {
|
||||
|
||||
@@ -127,3 +127,41 @@ func (l2db *L2DB) GetTxAPI(txID common.TxID) (*PoolTxAPI, error) {
|
||||
txID,
|
||||
))
|
||||
}
|
||||
|
||||
func (l2db *L2DB) GetPoolTxs(idx *common.Idx, state *common.PoolL2TxState) ([]*PoolTxAPI, error) {
|
||||
cancel, err := l2db.apiConnCon.Acquire()
|
||||
defer cancel()
|
||||
if err != nil {
|
||||
return nil, tracerr.Wrap(err)
|
||||
}
|
||||
defer l2db.apiConnCon.Release()
|
||||
// Apply filters
|
||||
nextIsAnd := false
|
||||
queryStr := selectPoolTxAPI
|
||||
var args []interface{}
|
||||
if state != nil {
|
||||
queryStr += "WHERE state = ? "
|
||||
args = append(args, state)
|
||||
nextIsAnd = true
|
||||
}
|
||||
if idx != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND ("
|
||||
} else {
|
||||
queryStr += "WHERE ("
|
||||
}
|
||||
queryStr += "tx_pool.from_idx = ? "
|
||||
queryStr += "OR tx_pool.to_idx = ?) "
|
||||
args = append(args, idx)
|
||||
args = append(args, idx)
|
||||
nextIsAnd = true
|
||||
}
|
||||
queryStr += "AND NOT external_delete;"
|
||||
query := l2db.dbRead.Rebind(queryStr)
|
||||
txs := []*PoolTxAPI{}
|
||||
err = meddler.QueryAll(
|
||||
l2db.dbRead, &txs,
|
||||
query,
|
||||
args...)
|
||||
return txs, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
@@ -311,6 +311,27 @@ func TestGetPending(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestL2DB_GetPoolTxs(t *testing.T) {
|
||||
err := prepareHistoryDB(historyDB)
|
||||
if err != nil {
|
||||
log.Error("Error prepare historyDB", err)
|
||||
}
|
||||
poolL2Txs, err := generatePoolL2Txs()
|
||||
state := common.PoolL2TxState("pend")
|
||||
idx := common.Idx(256)
|
||||
var pendingTxs []*common.PoolL2Tx
|
||||
for i := range poolL2Txs {
|
||||
if poolL2Txs[i].FromIdx == idx || poolL2Txs[i].ToIdx == idx {
|
||||
err := l2DB.AddTxTest(&poolL2Txs[i])
|
||||
require.NoError(t, err)
|
||||
pendingTxs = append(pendingTxs, &poolL2Txs[i])
|
||||
}
|
||||
}
|
||||
fetchedTxs, err := l2DBWithACC.GetPoolTxs(&idx, &state)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, len(pendingTxs), len(fetchedTxs))
|
||||
}
|
||||
|
||||
func TestStartForging(t *testing.T) {
|
||||
// Generate txs
|
||||
var fakeBatchNum common.BatchNum = 33
|
||||
|
||||
Reference in New Issue
Block a user