diff --git a/api/client.go b/api/client.go index e10a3bfa..c2d91af3 100644 --- a/api/client.go +++ b/api/client.go @@ -84,3 +84,9 @@ func (c *Client) Transaction(id types.TransactionID) (resp types.Transaction, er err = c.c.GET(fmt.Sprintf("/explorer/transactions/%s", id), &resp) return } + +// Transactions returns the transactions with the specified IDs. +func (c *Client) Transactions(ids []types.TransactionID) (resp types.Transaction, err error) { + err = c.c.POST("/explorer/transactions", ids, &resp) + return +} diff --git a/api/server.go b/api/server.go index 8ebcc616..34bd46ac 100644 --- a/api/server.go +++ b/api/server.go @@ -1,6 +1,7 @@ package api import ( + "errors" "net/http" "sync" @@ -177,6 +178,30 @@ func (s *server) explorerTransactionsIDHandler(jc jape.Context) { jc.Encode(txn) } +func (s *server) explorerTransactionsHandler(jc jape.Context) { + var ( + errTooManyIDs = errors.New("too many IDs provided (provide less than 5000)") + ) + + var ids []types.TransactionID + if jc.Decode(&ids) != nil { + return + } else if len(ids) > 5000 { + jc.Error(errTooManyIDs, http.StatusBadRequest) + return + } + + var txns []types.Transaction + for _, id := range ids { + txn, err := s.e.Transaction(id) + if jc.Check("failed to get transaction", err) != nil { + return + } + txns = append(txns, txn) + } + jc.Encode(txns) +} + // NewServer returns an HTTP handler that serves the explored API. func NewServer(e Explorer, cm ChainManager, s Syncer) http.Handler { srv := server{ @@ -197,5 +222,6 @@ func NewServer(e Explorer, cm ChainManager, s Syncer) http.Handler { "GET /explorer/block/id/:id": srv.explorerBlockHandler, "GET /explorer/block/height/:height": srv.explorerBlockHeightHandler, "GET /explorer/transactions/:id": srv.explorerTransactionsIDHandler, + "POST /explorer/transactions": srv.explorerTransactionsHandler, }) } diff --git a/persist/sqlite/init.sql b/persist/sqlite/init.sql index 6604d038..087eefdd 100644 --- a/persist/sqlite/init.sql +++ b/persist/sqlite/init.sql @@ -26,6 +26,8 @@ CREATE TABLE transactions ( transaction_id BLOB UNIQUE NOT NULL ); +CREATE INDEX transactions_index ON transactions(transaction_id); + CREATE TABLE block_transactions ( block_id BLOB REFERENCES blocks(id) ON DELETE CASCADE NOT NULL, transaction_id INTEGER REFERENCES transactions(id) ON DELETE CASCADE NOT NULL,