mirror of
https://github.com/luxfi/node.git
synced 2026-07-27 03:39:39 +00:00
144 lines
4.4 KiB
Go
144 lines
4.4 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package indexer
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/luxfi/formatting"
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/node/utils/json"
|
|
"github.com/luxfi/rpc"
|
|
)
|
|
|
|
type Client struct {
|
|
Requester rpc.EndpointRequester
|
|
}
|
|
|
|
// NewClient creates a client that can interact with an index via HTTP API
|
|
// calls.
|
|
// [uri] is the path to make API calls to.
|
|
// For example:
|
|
// - http://1.2.3.4:9650/ext/index/C/block
|
|
// - http://1.2.3.4:9650/ext/index/X/tx
|
|
func NewClient(uri string) *Client {
|
|
return &Client{
|
|
Requester: rpc.NewEndpointRequester(uri),
|
|
}
|
|
}
|
|
|
|
// GetContainerRange returns the transactions at index [startIndex], [startIndex+1], ... , [startIndex+n-1]
|
|
// If [n] == 0, returns an empty response (i.e. null).
|
|
// If [startIndex] > the last accepted index, returns an error (unless the above apply.)
|
|
// If we run out of transactions, returns the ones fetched before running out.
|
|
func (c *Client) GetContainerRange(ctx context.Context, startIndex uint64, numToFetch int, options ...rpc.Option) ([]Container, error) {
|
|
var fcs GetContainerRangeResponse
|
|
err := c.Requester.SendRequest(ctx, "index.getContainerRange", &GetContainerRangeArgs{
|
|
StartIndex: json.Uint64(startIndex),
|
|
NumToFetch: json.Uint64(numToFetch),
|
|
Encoding: formatting.Hex,
|
|
}, &fcs, options...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
response := make([]Container, len(fcs.Containers))
|
|
for i, resp := range fcs.Containers {
|
|
containerBytes, err := formatting.Decode(resp.Encoding, resp.Bytes)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("couldn't decode container %s: %w", resp.ID, err)
|
|
}
|
|
response[i] = Container{
|
|
ID: resp.ID,
|
|
Timestamp: resp.Timestamp.Unix(),
|
|
Bytes: containerBytes,
|
|
}
|
|
}
|
|
return response, nil
|
|
}
|
|
|
|
// Get a container by its index
|
|
func (c *Client) GetContainerByIndex(ctx context.Context, index uint64, options ...rpc.Option) (Container, error) {
|
|
var fc FormattedContainer
|
|
err := c.Requester.SendRequest(ctx, "index.getContainerByIndex", &GetContainerByIndexArgs{
|
|
Index: json.Uint64(index),
|
|
Encoding: formatting.Hex,
|
|
}, &fc, options...)
|
|
if err != nil {
|
|
return Container{}, err
|
|
}
|
|
|
|
containerBytes, err := formatting.Decode(fc.Encoding, fc.Bytes)
|
|
if err != nil {
|
|
return Container{}, fmt.Errorf("couldn't decode container %s: %w", fc.ID, err)
|
|
}
|
|
return Container{
|
|
ID: fc.ID,
|
|
Timestamp: fc.Timestamp.Unix(),
|
|
Bytes: containerBytes,
|
|
}, nil
|
|
}
|
|
|
|
// Get the most recently accepted container and its index
|
|
func (c *Client) GetLastAccepted(ctx context.Context, options ...rpc.Option) (Container, uint64, error) {
|
|
var fc FormattedContainer
|
|
err := c.Requester.SendRequest(ctx, "index.getLastAccepted", &GetLastAcceptedArgs{
|
|
Encoding: formatting.Hex,
|
|
}, &fc, options...)
|
|
if err != nil {
|
|
return Container{}, 0, err
|
|
}
|
|
|
|
containerBytes, err := formatting.Decode(fc.Encoding, fc.Bytes)
|
|
if err != nil {
|
|
return Container{}, 0, fmt.Errorf("couldn't decode container %s: %w", fc.ID, err)
|
|
}
|
|
return Container{
|
|
ID: fc.ID,
|
|
Timestamp: fc.Timestamp.Unix(),
|
|
Bytes: containerBytes,
|
|
}, uint64(fc.Index), nil
|
|
}
|
|
|
|
// Returns 1 less than the number of containers accepted on this chain
|
|
func (c *Client) GetIndex(ctx context.Context, id ids.ID, options ...rpc.Option) (uint64, error) {
|
|
var index GetIndexResponse
|
|
err := c.Requester.SendRequest(ctx, "index.getIndex", &GetIndexArgs{
|
|
ID: id,
|
|
}, &index, options...)
|
|
return uint64(index.Index), err
|
|
}
|
|
|
|
// Returns true if the given container is accepted
|
|
func (c *Client) IsAccepted(ctx context.Context, id ids.ID, options ...rpc.Option) (bool, error) {
|
|
var res IsAcceptedResponse
|
|
err := c.Requester.SendRequest(ctx, "index.isAccepted", &IsAcceptedArgs{
|
|
ID: id,
|
|
}, &res, options...)
|
|
return res.IsAccepted, err
|
|
}
|
|
|
|
// Get a container and its index by its ID
|
|
func (c *Client) GetContainerByID(ctx context.Context, id ids.ID, options ...rpc.Option) (Container, uint64, error) {
|
|
var fc FormattedContainer
|
|
err := c.Requester.SendRequest(ctx, "index.getContainerByID", &GetContainerByIDArgs{
|
|
ID: id,
|
|
Encoding: formatting.Hex,
|
|
}, &fc, options...)
|
|
if err != nil {
|
|
return Container{}, 0, err
|
|
}
|
|
|
|
containerBytes, err := formatting.Decode(fc.Encoding, fc.Bytes)
|
|
if err != nil {
|
|
return Container{}, 0, fmt.Errorf("couldn't decode container %s: %w", fc.ID, err)
|
|
}
|
|
return Container{
|
|
ID: fc.ID,
|
|
Timestamp: fc.Timestamp.Unix(),
|
|
Bytes: containerBytes,
|
|
}, uint64(fc.Index), nil
|
|
}
|