Commit 6c03aeba authored by Ethen Pociask's avatar Ethen Pociask

[indexer.client] Client support for paginated withdrawal queries

parent cf1f0b10
...@@ -30,6 +30,8 @@ type Api struct { ...@@ -30,6 +30,8 @@ type Api struct {
const ( const (
MetricsNamespace = "op_indexer" MetricsNamespace = "op_indexer"
DepositsPath = "/api/v0/deposits/{address:%s}"
WithdrawalsPath = "/api/v0/withdrawals/{address:%s}"
) )
func chiMetricsMiddleware(rec metrics.HTTPRecorder) func(http.Handler) http.Handler { func chiMetricsMiddleware(rec metrics.HTTPRecorder) func(http.Handler) http.Handler {
...@@ -49,8 +51,8 @@ func NewApi(logger log.Logger, bv database.BridgeTransfersView, serverConfig con ...@@ -49,8 +51,8 @@ func NewApi(logger log.Logger, bv database.BridgeTransfersView, serverConfig con
apiRouter.Use(middleware.Recoverer) apiRouter.Use(middleware.Recoverer)
apiRouter.Use(middleware.Heartbeat("/healthz")) apiRouter.Use(middleware.Heartbeat("/healthz"))
apiRouter.Get(fmt.Sprintf("/api/v0/deposits/{address:%s}", ethereumAddressRegex), h.L1DepositsHandler) apiRouter.Get(fmt.Sprintf(DepositsPath, ethereumAddressRegex), h.L1DepositsHandler)
apiRouter.Get(fmt.Sprintf("/api/v0/withdrawals/{address:%s}", ethereumAddressRegex), h.L2WithdrawalsHandler) apiRouter.Get(fmt.Sprintf(WithdrawalsPath, ethereumAddressRegex), h.L2WithdrawalsHandler)
return &Api{log: logger, Router: apiRouter, metricsRegistry: mr, serverConfig: serverConfig, metricsConfig: metricsConfig} return &Api{log: logger, Router: apiRouter, metricsRegistry: mr, serverConfig: serverConfig, metricsConfig: metricsConfig}
} }
......
package client
import (
"fmt"
"io/ioutil"
"net/http"
"encoding/json"
"github.com/ethereum-optimism/optimism/indexer/api"
"github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/indexer/node"
)
const (
urlParams = "?cursor=%s&limit=%d"
defaultPagingLimit = 100
)
// Config ... Indexer client config struct
type Config struct {
PaginationLimit int
URL string
}
// IndexerClient ... Indexer client struct
type IndexerClient struct {
cfg *Config
c *http.Client
m node.Metricer
}
// DialIndexerClient ... Dials indexer API URL
func DialIndexerClient(cfg *Config, m node.Metricer) (*IndexerClient, error) {
if cfg.PaginationLimit == 0 {
cfg.PaginationLimit = defaultPagingLimit
}
c := &http.Client{}
return &IndexerClient{cfg: cfg, c: c, m: m}, nil
}
// GetAllWithdrawalsByAddress ... Gets all withdrawals by address
func (ic *IndexerClient) GetAllWithdrawalsByAddress(l2Address string) ([]database.L2BridgeWithdrawalWithTransactionHashes, error) {
var withdrawals []database.L2BridgeWithdrawalWithTransactionHashes
cursor := ""
for {
wResponse, err := ic.GetWithdrawalsByAddress(l2Address, cursor)
if err != nil {
return nil, err
}
withdrawals = append(withdrawals, wResponse.Withdrawals...)
if !wResponse.HasNextPage {
break
}
cursor = wResponse.Cursor
}
return withdrawals, nil
}
// GetWithdrawalsByAddress ... Gets a withdrawal response object provided an L2 address
func (ic *IndexerClient) GetWithdrawalsByAddress(l2Address string, cursor string) (*database.L2BridgeWithdrawalsResponse, error) {
var wResponse *database.L2BridgeWithdrawalsResponse
endpoint := fmt.Sprintf(ic.cfg.URL+api.WithdrawalsPath+urlParams, l2Address, cursor, ic.cfg.PaginationLimit)
resp, err := ic.c.Get(endpoint)
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body: %w", err)
}
if err := json.Unmarshal(body, &wResponse); err != nil {
return nil, err
}
return wResponse, nil
}
...@@ -48,7 +48,7 @@ func DialEthClient(rpcUrl string, metrics Metricer) (EthClient, error) { ...@@ -48,7 +48,7 @@ func DialEthClient(rpcUrl string, metrics Metricer) (EthClient, error) {
return nil, err return nil, err
} }
client := &client{rpc: newRPC(rpcClient, metrics)} client := &client{rpc: NewRPC(rpcClient, metrics)}
return client, nil return client, nil
} }
...@@ -207,7 +207,7 @@ type rpcClient struct { ...@@ -207,7 +207,7 @@ type rpcClient struct {
metrics Metricer metrics Metricer
} }
func newRPC(client *rpc.Client, metrics Metricer) RPC { func NewRPC(client *rpc.Client, metrics Metricer) RPC {
return &rpcClient{client, metrics} return &rpcClient{client, metrics}
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment