Refactor api txs

This commit is contained in:
Arnau B
2020-10-26 16:47:16 +01:00
parent decc4996ee
commit a329d894d2
18 changed files with 1452 additions and 1272 deletions

View File

@@ -651,15 +651,16 @@ func (hdb *HistoryDB) addTxs(d meddler.DB, txs []txWrite) error {
// }
// GetHistoryTx returns a tx from the DB given a TxID
func (hdb *HistoryDB) GetHistoryTx(txID common.TxID) (*HistoryTx, error) {
tx := &HistoryTx{}
func (hdb *HistoryDB) GetHistoryTx(txID common.TxID) (*TxAPI, error) {
tx := &TxAPI{}
err := meddler.QueryRow(
hdb.db, tx, `SELECT tx.item_id, tx.is_l1, tx.id, tx.type, tx.position,
tx.from_idx, tx.to_idx, tx.amount, tx.token_id, tx.amount_usd,
hez_idx(tx.from_idx, token.symbol) AS from_idx, tx.from_eth_addr, tx.from_bjj,
hez_idx(tx.to_idx, token.symbol) AS to_idx, tx.to_eth_addr, tx.to_bjj,
tx.amount, tx.token_id, tx.amount_usd,
tx.batch_num, tx.eth_block_num, tx.to_forge_l1_txs_num, tx.user_origin,
tx.from_eth_addr, tx.from_bjj, tx.load_amount,
tx.load_amount_usd, tx.fee, tx.fee_usd, tx.nonce,
token.token_id, token.eth_block_num AS token_block,
tx.load_amount, tx.load_amount_usd, tx.fee, tx.fee_usd, tx.nonce,
token.token_id, token.item_id AS token_item_id, token.eth_block_num AS token_block,
token.eth_addr, token.name, token.symbol, token.decimals, token.usd,
token.usd_update, block.timestamp
FROM tx INNER JOIN token ON tx.token_id = token.token_id
@@ -675,18 +676,19 @@ func (hdb *HistoryDB) GetHistoryTxs(
ethAddr *ethCommon.Address, bjj *babyjub.PublicKey,
tokenID *common.TokenID, idx *common.Idx, batchNum *uint, txType *common.TxType,
fromItem, limit *uint, order string,
) ([]HistoryTx, *db.Pagination, error) {
) ([]TxAPI, *db.Pagination, error) {
if ethAddr != nil && bjj != nil {
return nil, nil, errors.New("ethAddr and bjj are incompatible")
}
var query string
var args []interface{}
queryStr := `SELECT tx.item_id, tx.is_l1, tx.id, tx.type, tx.position,
tx.from_idx, tx.to_idx, tx.amount, tx.token_id, tx.amount_usd,
hez_idx(tx.from_idx, token.symbol) AS from_idx, tx.from_eth_addr, tx.from_bjj,
hez_idx(tx.to_idx, token.symbol) AS to_idx, tx.to_eth_addr, tx.to_bjj,
tx.amount, tx.token_id, tx.amount_usd,
tx.batch_num, tx.eth_block_num, tx.to_forge_l1_txs_num, tx.user_origin,
tx.from_eth_addr, tx.from_bjj, tx.load_amount,
tx.load_amount_usd, tx.fee, tx.fee_usd, tx.nonce,
token.token_id, token.eth_block_num AS token_block,
tx.load_amount, tx.load_amount_usd, tx.fee, tx.fee_usd, tx.nonce,
token.token_id, token.item_id AS token_item_id, token.eth_block_num AS token_block,
token.eth_addr, token.name, token.symbol, token.decimals, token.usd,
token.usd_update, block.timestamp, count(*) OVER() AS total_items,
MIN(tx.item_id) OVER() AS first_item, MAX(tx.item_id) OVER() AS last_item
@@ -783,11 +785,11 @@ func (hdb *HistoryDB) GetHistoryTxs(
queryStr += fmt.Sprintf("LIMIT %d;", *limit)
query = hdb.db.Rebind(queryStr)
log.Debug(query)
txsPtrs := []*HistoryTx{}
txsPtrs := []*TxAPI{}
if err := meddler.QueryAll(hdb.db, &txsPtrs, query, args...); err != nil {
return nil, nil, err
}
txs := db.SlicePtrsToSlice(txsPtrs).([]HistoryTx)
txs := db.SlicePtrsToSlice(txsPtrs).([]TxAPI)
if len(txs) == 0 {
return nil, nil, sql.ErrNoRows
}

View File

@@ -1,6 +1,7 @@
package historydb
import (
"encoding/json"
"math/big"
"time"
@@ -11,29 +12,30 @@ import (
"github.com/iden3/go-merkletree"
)
// HistoryTx is a representation of a generic Tx with additional information
// TxAPI is a representation of a generic Tx with additional information
// required by the API, and extracted by joining block and token tables
type HistoryTx struct {
type TxAPI struct {
// Generic
IsL1 bool `meddler:"is_l1"`
TxID common.TxID `meddler:"id"`
ItemID int `meddler:"item_id"`
Type common.TxType `meddler:"type"`
Position int `meddler:"position"`
FromIdx *common.Idx `meddler:"from_idx"`
ToIdx common.Idx `meddler:"to_idx"`
Amount *big.Int `meddler:"amount,bigint"`
HistoricUSD *float64 `meddler:"amount_usd"`
BatchNum *common.BatchNum `meddler:"batch_num"` // batchNum in which this tx was forged. If the tx is L2, this must be != 0
EthBlockNum int64 `meddler:"eth_block_num"` // Ethereum Block Number in which this L1Tx was added to the queue
IsL1 bool `meddler:"is_l1"`
TxID common.TxID `meddler:"id"`
ItemID int `meddler:"item_id"`
Type common.TxType `meddler:"type"`
Position int `meddler:"position"`
FromIdx *apitypes.HezIdx `meddler:"from_idx"`
FromEthAddr *apitypes.HezEthAddr `meddler:"from_eth_addr"`
FromBJJ *apitypes.HezBJJ `meddler:"from_bjj"`
ToIdx apitypes.HezIdx `meddler:"to_idx"`
ToEthAddr *apitypes.HezEthAddr `meddler:"to_eth_addr"`
ToBJJ *apitypes.HezBJJ `meddler:"to_bjj"`
Amount apitypes.BigIntStr `meddler:"amount"`
HistoricUSD *float64 `meddler:"amount_usd"`
BatchNum *common.BatchNum `meddler:"batch_num"` // batchNum in which this tx was forged. If the tx is L2, this must be != 0
EthBlockNum int64 `meddler:"eth_block_num"` // Ethereum Block Number in which this L1Tx was added to the queue
// L1
ToForgeL1TxsNum *int64 `meddler:"to_forge_l1_txs_num"` // toForgeL1TxsNum in which the tx was forged / will be forged
UserOrigin *bool `meddler:"user_origin"` // true if the tx was originated by a user, false if it was aoriginated by a coordinator. Note that this differ from the spec for implementation simplification purpposes
FromEthAddr *ethCommon.Address `meddler:"from_eth_addr"`
FromBJJ *babyjub.PublicKey `meddler:"from_bjj"`
LoadAmount *big.Int `meddler:"load_amount,bigintnull"`
// LoadAmountFloat *float64 `meddler:"load_amount_f"`
HistoricLoadAmountUSD *float64 `meddler:"load_amount_usd"`
ToForgeL1TxsNum *int64 `meddler:"to_forge_l1_txs_num"` // toForgeL1TxsNum in which the tx was forged / will be forged
UserOrigin *bool `meddler:"user_origin"` // true if the tx was originated by a user, false if it was aoriginated by a coordinator. Note that this differ from the spec for implementation simplification purpposes
LoadAmount *apitypes.BigIntStr `meddler:"load_amount"`
HistoricLoadAmountUSD *float64 `meddler:"load_amount_usd"`
// L2
Fee *common.FeeSelector `meddler:"fee"`
HistoricFeeUSD *float64 `meddler:"fee_usd"`
@@ -44,6 +46,7 @@ type HistoryTx struct {
FirstItem int `meddler:"first_item"`
LastItem int `meddler:"last_item"`
TokenID common.TokenID `meddler:"token_id"`
TokenItemID int `meddler:"token_item_id"`
TokenEthBlockNum int64 `meddler:"token_block"`
TokenEthAddr ethCommon.Address `meddler:"eth_addr"`
TokenName string `meddler:"name"`
@@ -53,6 +56,58 @@ type HistoryTx struct {
TokenUSDUpdate *time.Time `meddler:"usd_update"`
}
// MarshalJSON is used to neast some of the fields of TxAPI
// without the need of auxiliar structs
func (tx TxAPI) MarshalJSON() ([]byte, error) {
jsonTx := map[string]interface{}{
"id": tx.TxID,
"itemId": tx.ItemID,
"type": tx.Type,
"position": tx.Position,
"fromAccountIndex": tx.FromIdx,
"fromHezEthereumAddress": tx.FromEthAddr,
"fromBJJ": tx.FromBJJ,
"toAccountIndex": tx.ToIdx,
"toHezEthereumAddress": tx.ToEthAddr,
"toBJJ": tx.ToBJJ,
"amount": tx.Amount,
"batchNum": tx.BatchNum,
"historicUSD": tx.HistoricUSD,
"timestamp": tx.Timestamp,
"L1Info": nil,
"L2Info": nil,
"token": map[string]interface{}{
"id": tx.TokenID,
"itemId": tx.TokenItemID,
"ethereumBlockNum": tx.TokenEthBlockNum,
"ethereumAddress": tx.TokenEthAddr,
"name": tx.TokenName,
"symbol": tx.TokenSymbol,
"decimals": tx.TokenDecimals,
"USD": tx.TokenUSD,
"fiatUpdate": tx.TokenUSDUpdate,
},
}
if tx.IsL1 {
jsonTx["L1orL2"] = "L1"
jsonTx["L1Info"] = map[string]interface{}{
"toForgeL1TransactionsNum": tx.ToForgeL1TxsNum,
"userOrigin": tx.UserOrigin,
"loadAmount": tx.LoadAmount,
"historicLoadAmountUSD": tx.HistoricLoadAmountUSD,
"ethereumBlockNum": tx.EthBlockNum,
}
} else {
jsonTx["L1orL2"] = "L2"
jsonTx["L2Info"] = map[string]interface{}{
"fee": tx.Fee,
"historicFeeUSD": tx.HistoricFeeUSD,
"nonce": tx.Nonce,
}
}
return json.Marshal(jsonTx)
}
// txWrite is an representatiion that merges common.L1Tx and common.L2Tx
// in order to perform inserts into tx table
type txWrite struct {