mirror of
https://github.com/arnaucube/hermez-node.git
synced 2026-02-07 03:16:45 +01:00
Account API
This commit is contained in:
@@ -1332,9 +1332,7 @@ func (hdb *HistoryDB) AddBlockSCData(blockData *common.BlockData) (err error) {
|
||||
// GetCoordinatorAPI returns a coordinator by its bidderAddr
|
||||
func (hdb *HistoryDB) GetCoordinatorAPI(bidderAddr ethCommon.Address) (*CoordinatorAPI, error) {
|
||||
coordinator := &CoordinatorAPI{}
|
||||
err := meddler.QueryRow(
|
||||
hdb.db, coordinator, `SELECT * FROM coordinator WHERE bidder_addr = $1;`, bidderAddr,
|
||||
)
|
||||
err := meddler.QueryRow(hdb.db, coordinator, "SELECT * FROM coordinator WHERE bidder_addr = $1;", bidderAddr)
|
||||
return coordinator, err
|
||||
}
|
||||
|
||||
@@ -1392,3 +1390,95 @@ func (hdb *HistoryDB) GetAuctionVars() (*common.AuctionVariables, error) {
|
||||
)
|
||||
return auctionVars, err
|
||||
}
|
||||
|
||||
// GetAccountAPI returns an account by its index
|
||||
func (hdb *HistoryDB) GetAccountAPI(idx common.Idx) (*AccountAPI, error) {
|
||||
account := &AccountAPI{}
|
||||
err := meddler.QueryRow(hdb.db, account, `SELECT account.item_id, hez_idx(account.idx, token.symbol) as idx, account.batch_num, account.bjj, account.eth_addr,
|
||||
token.token_id, token.item_id AS token_item_id, token.eth_block_num AS token_block,
|
||||
token.eth_addr as token_eth_addr, token.name, token.symbol, token.decimals, token.usd, token.usd_update
|
||||
FROM account INNER JOIN token ON account.token_id = token.token_id WHERE idx = $1;`, idx)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return account, nil
|
||||
}
|
||||
|
||||
// GetAccountsAPI returns a list of accounts from the DB and pagination info
|
||||
func (hdb *HistoryDB) GetAccountsAPI(tokenIDs []common.TokenID, ethAddr *ethCommon.Address, bjj *babyjub.PublicKey, fromItem, limit *uint, order string) ([]AccountAPI, *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 account.item_id, hez_idx(account.idx, token.symbol) as idx, account.batch_num, account.bjj, account.eth_addr,
|
||||
token.token_id, token.item_id AS token_item_id, token.eth_block_num AS token_block,
|
||||
token.eth_addr as token_eth_addr, token.name, token.symbol, token.decimals, token.usd, token.usd_update,
|
||||
COUNT(*) OVER() AS total_items, MIN(account.item_id) OVER() AS first_item, MAX(account.item_id) OVER() AS last_item
|
||||
FROM account INNER JOIN token ON account.token_id = token.token_id `
|
||||
// Apply filters
|
||||
nextIsAnd := false
|
||||
// ethAddr filter
|
||||
if ethAddr != nil {
|
||||
queryStr += "WHERE account.eth_addr = ? "
|
||||
nextIsAnd = true
|
||||
args = append(args, ethAddr)
|
||||
} else if bjj != nil { // bjj filter
|
||||
queryStr += "WHERE account.bjj = ? "
|
||||
nextIsAnd = true
|
||||
args = append(args, bjj)
|
||||
}
|
||||
// tokenID filter
|
||||
if len(tokenIDs) > 0 {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
queryStr += "account.token_id IN (?) "
|
||||
args = append(args, tokenIDs)
|
||||
nextIsAnd = true
|
||||
}
|
||||
if fromItem != nil {
|
||||
if nextIsAnd {
|
||||
queryStr += "AND "
|
||||
} else {
|
||||
queryStr += "WHERE "
|
||||
}
|
||||
if order == OrderAsc {
|
||||
queryStr += "account.item_id >= ? "
|
||||
} else {
|
||||
queryStr += "account.item_id <= ? "
|
||||
}
|
||||
args = append(args, fromItem)
|
||||
}
|
||||
// pagination
|
||||
queryStr += "ORDER BY account.item_id "
|
||||
if order == OrderAsc {
|
||||
queryStr += " ASC "
|
||||
} else {
|
||||
queryStr += " DESC "
|
||||
}
|
||||
queryStr += fmt.Sprintf("LIMIT %d;", *limit)
|
||||
query, argsQ, err := sqlx.In(queryStr, args...)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
query = hdb.db.Rebind(query)
|
||||
|
||||
accounts := []*AccountAPI{}
|
||||
if err := meddler.QueryAll(hdb.db, &accounts, query, argsQ...); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if len(accounts) == 0 {
|
||||
return nil, nil, sql.ErrNoRows
|
||||
}
|
||||
|
||||
return db.SlicePtrsToSlice(accounts).([]AccountAPI), &db.Pagination{
|
||||
TotalItems: accounts[0].TotalItems,
|
||||
FirstItem: accounts[0].FirstItem,
|
||||
LastItem: accounts[0].LastItem,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -228,6 +228,55 @@ type CoordinatorAPI struct {
|
||||
LastItem int `json:"-" meddler:"last_item"`
|
||||
}
|
||||
|
||||
// AccountAPI is a representation of a account with additional information
|
||||
// required by the API
|
||||
type AccountAPI struct {
|
||||
ItemID int `meddler:"item_id"`
|
||||
Idx apitypes.HezIdx `meddler:"idx"`
|
||||
BatchNum common.BatchNum `meddler:"batch_num"`
|
||||
PublicKey apitypes.HezBJJ `meddler:"bjj"`
|
||||
EthAddr apitypes.HezEthAddr `meddler:"eth_addr"`
|
||||
Nonce common.Nonce `meddler:"-"` // max of 40 bits used
|
||||
Balance *apitypes.BigIntStr `meddler:"-"` // max of 192 bits used
|
||||
TotalItems int `meddler:"total_items"`
|
||||
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:"token_eth_addr"`
|
||||
TokenName string `meddler:"name"`
|
||||
TokenSymbol string `meddler:"symbol"`
|
||||
TokenDecimals uint64 `meddler:"decimals"`
|
||||
TokenUSD *float64 `meddler:"usd"`
|
||||
TokenUSDUpdate *time.Time `meddler:"usd_update"`
|
||||
}
|
||||
|
||||
// MarshalJSON is used to neast some of the fields of AccountAPI
|
||||
// without the need of auxiliar structs
|
||||
func (account AccountAPI) MarshalJSON() ([]byte, error) {
|
||||
jsonAccount := map[string]interface{}{
|
||||
"itemId": account.ItemID,
|
||||
"accountIndex": account.Idx,
|
||||
"nonce": account.Nonce,
|
||||
"balance": account.Balance,
|
||||
"bjj": account.PublicKey,
|
||||
"hezEthereumAddress": account.EthAddr,
|
||||
"token": map[string]interface{}{
|
||||
"id": account.TokenID,
|
||||
"itemId": account.TokenItemID,
|
||||
"ethereumBlockNum": account.TokenEthBlockNum,
|
||||
"ethereumAddress": account.TokenEthAddr,
|
||||
"name": account.TokenName,
|
||||
"symbol": account.TokenSymbol,
|
||||
"decimals": account.TokenDecimals,
|
||||
"USD": account.TokenUSD,
|
||||
"fiatUpdate": account.TokenUSDUpdate,
|
||||
},
|
||||
}
|
||||
return json.Marshal(jsonAccount)
|
||||
}
|
||||
|
||||
// BatchAPI is a representation of a batch with additional information
|
||||
// required by the API, and extracted by joining block table
|
||||
type BatchAPI struct {
|
||||
|
||||
@@ -94,6 +94,7 @@ LANGUAGE plpgsql;
|
||||
-- +migrate StatementEnd
|
||||
|
||||
CREATE TABLE account (
|
||||
item_id SERIAL,
|
||||
idx BIGINT PRIMARY KEY,
|
||||
token_id INT NOT NULL REFERENCES token (token_id) ON DELETE CASCADE,
|
||||
batch_num BIGINT NOT NULL REFERENCES batch (batch_num) ON DELETE CASCADE,
|
||||
|
||||
Reference in New Issue
Block a user