Documentation
¶
Overview ¶
Package indexer is a minimal client for a tx-indexer GraphQL endpoint. It knows nothing about gnoweb, which is what keeps it removable.
Index ¶
- Variables
- func Redact(raw string) string
- func ValidateURL(raw string) error
- type Block
- type Client
- func (c *Client) Block(ctx context.Context, height int) (*Block, error)
- func (c *Client) CallsBetween(ctx context.Context, lower, upper int) ([]Tx, error)
- func (c *Client) Deploys(ctx context.Context, pkgPath string, limit int) ([]Tx, error)
- func (c *Client) DeploysImporting(ctx context.Context, pkgPath string, limit int) ([]Tx, error)
- func (c *Client) DeploysQuoting(ctx context.Context, pkgPath string, lower, upper int) ([]Tx, error)
- func (c *Client) LatestBlockHeight(ctx context.Context) (int, error)
- func (c *Client) Query(ctx context.Context, query string, out any) error
- func (c *Client) RecentByAddress(ctx context.Context, addr string, limit int) ([]Tx, error)
- func (c *Client) RecentByPackage(ctx context.Context, pkgPath string, limit int) ([]Tx, error)
- func (c *Client) SourceContains(ctx context.Context, text, author string, limit int) ([]Tx, error)
- func (c *Client) TxByHash(ctx context.Context, hash string) (*Tx, error)
- func (c *Client) URL() string
- type Message
- type Tx
Constants ¶
This section is empty.
Variables ¶
var ErrNotFound = errors.New("not found")
ErrNotFound describes the question, not the indexer's health, so it never counts against the breaker.
var ErrPartial = errors.New("searched the most recent blocks only")
ErrPartial reports that a walk stopped short of genesis with fewer rows than asked for: the rows returned are the newest, and older ones may exist below the lowest band searched. It is not a failure, and the rows travel with it.
var ErrResponseTooLarge = errors.New("indexer response too large")
ErrResponseTooLarge is refused before decoding. On a recorded query it counts against the breaker: it describes the endpoint.
var ErrTooLarge = errors.New("indexer result set hit the element cap")
ErrTooLarge reports the server-side element cap. The response is partial, not empty: the resolver returns the rows it walked before stopping.
ErrUnavailable is returned while the breaker is open, without a request.
Functions ¶
func Redact ¶
Redact reduces an endpoint to its scheme and host. Userinfo and a query string are where an operator puts an indexer credential, and the endpoint is shown to every anonymous reader; the path goes too, since a key can sit there as well.
func ValidateURL ¶
ValidateURL rejects an endpoint the client could never reach, so a typo fails at startup rather than behind a log line calling the indexer enabled. `localhost:8546/graphql` parses, with "localhost" as its scheme.
Types ¶
type Block ¶
type Block struct {
Hash string `json:"hash"`
Height int `json:"height"`
ChainID string `json:"chain_id"`
Time time.Time `json:"time"`
NumTxs int `json:"num_txs"`
}
Block is a block header.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a tx-indexer GraphQL client. Callers hold it behind a nilable interface; that nil check is the feature switch.
func New ¶
New returns a Client for a tx-indexer GraphQL endpoint, e.g. https://indexer.gno.land/graphql/query. An empty token means no Authorization header is sent.
The URL may carry credentials, as userinfo or a query-string key; they are sent to the indexer and never shown: URL reports the redacted form.
func (*Client) CallsBetween ¶
CallsBetween returns every transaction carrying a MsgCall in the heights (lower, upper], in one query.
The band is all or nothing: when it holds more rows than the indexer's element cap the error wraps ErrTooLarge and no rows are returned, because a count over part of a band would read as a complete one. The caller narrows the band instead.
func (*Client) DeploysImporting ¶
DeploysImporting returns the newest deploys whose source holds pkgPath as a Go string literal, interpreted ("…") or raw (`…`), which is how an import names it. A bare substring would also match gno.land/r/demo/foobar, and the gnomod.toml of every gno.land/r/demo/foo/<sub>.
A transaction matches when any package it deploys matches, and comes back whole: the caller keeps the deploy messages and still cannot tell which of a batch matched.
func (*Client) DeploysQuoting ¶
func (c *Client) DeploysQuoting(ctx context.Context, pkgPath string, lower, upper int) ([]Tx, error)
DeploysQuoting returns every deploy in the heights (lower, upper] whose source holds pkgPath as a Go string literal, interpreted ("…") or raw (`…`), which is how an import names it. Unlike SourceContains it does not stop at the newest few: a caller asking who imports a package needs every candidate, and walks the chain band by band to get them, since a scan of the whole chain outlasts the client's request timeout.
A transaction matches when any package it deploys contains text, so a batched deploy brings along packages that do not. The caller has to check each one.
When the answer exceeds the indexer's element cap, the rows it kept are returned along with an error wrapping ErrTooLarge, so the caller can say "at least".
func (*Client) LatestBlockHeight ¶
LatestBlockHeight returns the chain tip, cached briefly. It doubles as the freshness stamp, so a panel can say how far behind the indexer is.
func (*Client) Query ¶
Query executes a GraphQL document and decodes `data` into out.
The query is a raw string so several fields can ride in one document. Values are interpolated through gqlString — deliberately the only escaping mechanism here.
func (*Client) RecentByAddress ¶
RecentByAddress returns the most recent transactions an address took part in, as caller, deployer, sender or recipient.
func (*Client) RecentByPackage ¶
RecentByPackage returns the most recent transactions touching a package, either calling into it or deploying it.
func (*Client) SourceContains ¶
SourceContains matches a substring over every deployed file body — the most expensive query tx-indexer answers. Deployed source, not rendered output: nothing indexes what Render() prints.
A non-empty author narrows the match on the indexer's side, to deploys whose creator is that address or whose path sits in that namespace. Filtering the capped answer instead would miss an author's older packages whenever newer matches by others fill the page.
type Message ¶
type Message struct {
Value struct {
Type string `json:"__typename"`
Caller string `json:"caller"`
PkgPath string `json:"pkg_path"`
Func string `json:"func"`
Creator string `json:"creator"`
From string `json:"from_address"`
To string `json:"to_address"`
Amount string `json:"amount"`
Package *struct {
Path string `json:"path"`
} `json:"package"`
} `json:"value"`
}
Message flattens the MessageValue union; Type names the populated group.
type Tx ¶
type Tx struct {
Hash string `json:"hash"`
Height int `json:"block_height"`
Success bool `json:"success"`
GasUsed int `json:"gas_used"`
Messages []Message `json:"messages"`
}
Tx is the subset this package selects. Never file bodies: a deploy carries its whole source, and a page of them is megabytes.