glassnode

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 12, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

README

Glassnode Go client

Go Reference CI Go version License

A Go client for the Glassnode API. It covers metric time series, bulk metrics, asset and metric metadata, and API usage. It has no dependencies outside the standard library.

Installation

go get github.com/glassnode/glassnode-api-go-client

The client requires Go 1.24 or later. Full API documentation is on pkg.go.dev.

Quick start

You need a Glassnode API key; see API Setup for how to create one.

package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"time"

	glassnode "github.com/glassnode/glassnode-api-go-client"
)

func main() {
	client, err := glassnode.NewClient(os.Getenv("GLASSNODE_API_KEY"))
	if err != nil {
		log.Fatal(err)
	}

	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	points, err := client.GetTimeSeries(ctx, "market/price_usd_close", &glassnode.MetricParams{
		Asset:    "BTC",
		Since:    time.Now().AddDate(0, 0, -30),
		Interval: "24h",
	})
	if err != nil {
		log.Fatal(err)
	}

	for _, p := range points {
		if p.Value == nil {
			continue // no data for this timestamp
		}
		fmt.Printf("%s  %.2f\n", time.Unix(p.Timestamp, 0).UTC().Format(time.DateOnly), *p.Value)
	}
}

A Client is safe for concurrent use; create one and share it. The client never reads environment variables or files on its own: the example above reads the key itself and passes it in.

Fetching data

Pick the method that matches the shape of the metric's response:

Data Method
Scalar metric, {"t", "v"} GetTimeSeries
Object metric (OHLC, breakdowns), {"t", "o"} GetObjectTimeSeries
Several assets in one request GetBulkMetric
Any other shape GetMetric with your own destination type
A metric as CSV, written to an io.Writer GetMetricCSV
Metric metadata, variants and availability GetMetricMetadata
Data lag percentiles GetMetricStats
Available metric paths ListMetrics
Asset metadata ListAssets
Metric tags, asset tags, categories, blockchains ListMetricTags, ListAssetTags, ListAssetCategories, ListAssetBlockchains
Exchanges, networks, miners ListExchanges, ListNetworks, ListMiners
Account allowance and usage GetAPIUsage, then Allowance()
Endpoints without a dedicated method Get (decodes JSON) or Raw (returns bytes)

Things to keep in mind:

  • Metric paths are written as in the API docs, with or without a leading slash: market/price_usd_close.
  • Timestamps are Unix seconds.
  • Missing values are nil, so a gap is never confused with a zero.
  • Point-in-time metrics (*_pit) also report when each value was computed, in ComputedAt; for other metrics it is nil.
  • params may be nil. The asset list methods take an optional CEL filter expression; pass "" for no filter.
Bulk metrics

Bulk endpoints return a metric for many assets, exchanges or other selectors in one request. Pass the base metric path; the client adds the /bulk suffix and unwraps the response envelope.

points, err := client.GetBulkMetric(ctx, "distribution/balance_exchanges", &glassnode.MetricParams{
	Assets:    []string{"BTC", "ETH"},
	Exchanges: []string{"binance", "coinbase"},
	Since:     time.Now().AddDate(0, 0, -7),
	Interval:  "24h",
})
for _, point := range points {
	for _, entry := range point.Bulk {
		fmt.Println(point.Timestamp, entry.Asset(), entry.Params["e"], entry.Value)
	}
}

Each entry carries the selectors that identify it in Params (for example a, e, network, or category for object metrics). Selector values are strings; a value of another JSON type, should the API ever send one, is kept as its JSON text and written back as a string by json.Marshal. Bulk requests differ from regular ones:

  • Since is required, and one request covers at most 10 days at 10m and 1h, 31 days at 24h, and 93 days at 1w and 1month resolution.
  • Every combination of selectors is billed like a separate request, and leaving out Assets selects all assets. Always set the selectors you need.
  • Bulk endpoints are not available on the Light API.
Allowance and usage

An account's API allowance is either monthly, in credits, or daily, in requests (the Advanced plan's Light API). Allowance pairs the limit with the counter of the same period, so the remainder is right for both:

usage, err := client.GetAPIUsage(ctx)
if err != nil {
	return err
}
if allowance, ok := usage.Allowance(); ok {
	fmt.Printf("%s: %d of %d used\n", allowance.Period, allowance.Used, allowance.Limit)
}

ok is false when the account has no add-on or when its add-ons report an unknown or mixed period; the raw APIAddons, CreditsUsed and DailyRequestsUsed are still available.

Additional parameters

MetricParams has typed fields for the common parameters (asset, exchanges, time range, interval, currency). Use Extra for anything else that a metric accepts. Values with several entries are sent as repeated query parameters.

params := &glassnode.MetricParams{
	Asset:     "BTC",
	Exchanges: []string{"binance"},
	Extra:     url.Values{"quote_symbol": {"USDT"}},
}

Set each parameter in one place only: setting it both in a typed field and in Extra is an error.

CSV downloads

GetMetricCSV asks the API for CSV and copies the response to a writer as it arrives, so a file of any size can be downloaded without holding it in memory:

file, err := os.Create("price.csv")
if err != nil {
	return err
}
defer file.Close()
err = client.GetMetricCSV(ctx, "market/price_usd_close", &glassnode.MetricParams{
	Asset:    "BTC",
	Since:    time.Now().AddDate(0, -1, 0),
	Interval: "24h",
}, file)

The columns are the API's (timestamp,value, the object keys for object metrics, computed_at for point-in-time metrics). Bulk metrics are not available in CSV. A failure before the body starts is retried like any other request; a failure while copying is not, since part of the file has been written.

Custom response types

GetMetric decodes into any pointer you pass, so you can define a struct for an unusual metric, add your own UnmarshalJSON validation, or keep the raw response with json.RawMessage. Use pointer fields for values that can be null. When decoding into any, numbers become json.Number, so large integers keep their precision.

Configuration

NewClient works without options. The defaults are:

Setting Default Option
Authentication API key in the X-Api-Key header WithAPIKeyInQuery, WithBearerToken, WithTokenSource
Timeout 1 minute per HTTP attempt WithTimeout
Retries 2 retries, backoff capped at 65s WithRetryPolicy
Response size Unlimited WithMaxResponseBytes
HTTP client Fresh http.Client WithHTTPClient
Base URL https://api.glassnode.com WithBaseURL
User agent glassnode-api-go-client WithUserAgent
client, err := glassnode.NewClient(apiKey,
	glassnode.WithTimeout(15*time.Second),
	glassnode.WithRetryPolicy(glassnode.RetryPolicy{
		MaxRetries: 3,
		BaseDelay:  500 * time.Millisecond,
		MaxDelay:   10 * time.Second,
	}),
	glassnode.WithUserAgent("my-service/1.2"),
)
Authentication

Most applications should use an API key. The client sends it in the X-Api-Key header, which keeps it out of URLs and access logs. WithAPIKeyInQuery sends it as the api_key query parameter instead, for setups that require it.

If your application already has a Glassnode OAuth access token, pass an empty API key and use one of the bearer-token options instead. The client does not implement the OAuth login flow; it only sends the token you give it.

  • WithBearerToken(token) sends a fixed token. Use it for short-lived scripts.
  • WithTokenSource(source) calls source before every HTTP attempt, including retries, so it can return a refreshed token. It must be safe for concurrent use and should respect context cancellation.

For example, to reuse a token source from golang.org/x/oauth2:

source := glassnode.TokenSourceFunc(func(ctx context.Context) (string, error) {
	token, err := oauthTokens.Token() // an oauth2.TokenSource
	if err != nil {
		return "", err
	}
	return token.AccessToken, nil
})
client, err := glassnode.NewClient("", glassnode.WithTokenSource(source))

Configure exactly one way to authenticate; NewClient returns an error otherwise. A failing token source produces an AuthError and is not retried. A 401 response is returned as is, unless the token source also implements TokenRefresher: then Refresh is called once and the request is repeated with the new token, so an application can recover from a token revoked before its expiry.

Timeouts and retries

The timeout applies to each HTTP attempt separately and covers the whole exchange, including reading the response body. A large response over a slow link, such as a full history with GetMetricCSV or a long Get, can exceed the default minute; raise it with WithTimeout or remove it with WithTimeout(0) and bound the call with a context deadline instead. A context deadline limits the total time of a call, including retries and the waits between them.

GET requests are retried after network errors and 429 or 5xx responses. Other errors, including 4xx responses and responses that fail to decode, are returned immediately. The delay before retry n is a random duration between zero and BaseDelay × 2ⁿ⁻¹, capped at MaxDelay (with the defaults: up to 1s, then up to 2s). A Retry-After header raises the delay to at least the value the server asks for; if that is longer than MaxDelay, the client returns the error instead of waiting. When a 429 response has no Retry-After, the client uses the API's x-rate-limit-reset header the same way. The wait the server asked for is available as APIError.RetryAfter, so you can wait and retry yourself when it exceeds MaxDelay. WithRetryPolicy(glassnode.RetryPolicy{}) disables retries.

The client has no cache and no rate limiter.

Large responses

A response is read completely before it is decoded, so a call holds the response body and the decoded values in memory at the same time. The API does not page results: a full history at 10m resolution is hundreds of megabytes. Limit the time range with Since and Until where possible. To bound memory where failing is preferable to growing, set WithMaxResponseBytes; a larger response then fails with a *ResponseTooLargeError and is not retried.

Custom HTTP client

WithHTTPClient lets you supply your own transport, for example for tracing, metrics or a proxy. The client copies the http.Client and keeps its transport, cookie jar and timeout. An explicit WithTimeout takes precedence over the supplied client's timeout.

Redirects are never followed, even with a custom client, so credentials are never sent to another host. A 3xx response is returned as an APIError.

If the supplied client already retries, for example one built with go-retryablehttp, disable the client's own retries with WithRetryPolicy(glassnode.RetryPolicy{}); otherwise both layers retry and a failing request can take many times longer than either policy intends.

Error handling

All errors can be inspected with errors.As and errors.Is:

points, err := client.GetTimeSeries(ctx, path, params)

var apiErr *glassnode.APIError
switch {
case errors.Is(err, context.DeadlineExceeded):
	// The context deadline or the HTTP timeout expired.
case errors.As(err, &apiErr):
	log.Printf("API returned %d for %s: %s", apiErr.StatusCode, apiErr.Endpoint, apiErr.Detail)
case err != nil:
	log.Print(err)
}
Error Meaning
*APIError The API responded with a non-2xx status. Detail holds the server's message, shortened to 300 characters; RetryAfter is the wait the server asked for, if any.
*InputError Invalid configuration or arguments; no request was sent.
*TransportError The request failed on the network or while reading the response.
*DecodeError The response did not match the expected type.
*AuthError The token source failed or returned an invalid token.
*ResponseTooLargeError The response exceeded WithMaxResponseBytes; also matches errors.Is(err, ErrResponseTooLarge).

Context cancellation and deadlines are returned as context.Canceled and context.DeadlineExceeded.

Error messages never contain the API key or tokens used for the call. The original underlying error is still available through errors.Unwrap, and it is not redacted, so avoid logging it on its own.

Examples

The examples directory contains runnable programs for the main use cases. Clone the repository and run them with your API key:

cd examples
export GLASSNODE_API_KEY=your-api-key
go run ./price

See examples/README.md for the full list.

Development

go test -race ./...
golangci-lint run ./...
(cd examples && go build ./... && golangci-lint run ./...)

Tests run against local HTTP servers and recorded API responses, so they need no API key. CI runs the same checks on the oldest supported and the latest Go release, plus govulncheck. Releases are tagged vX.Y.Z; the tag's section in CHANGELOG.md becomes the GitHub release notes. Design decisions are described in docs/design.md.

Contributing

Bug reports and pull requests are welcome; see CONTRIBUTING.md for how to set up a development environment and what a change needs. To report a security issue, follow SECURITY.md rather than opening a public issue. This project follows the Contributor Covenant code of conduct.

License

Apache License 2.0; see LICENSE and NOTICE.

Documentation

Overview

Package glassnode is a client for the Glassnode API (https://docs.glassnode.com).

Create a Client with NewClient and reuse it; it is safe for concurrent use. Every method takes a context.Context, which controls cancellation and the overall deadline of the call, including retries:

client, err := glassnode.NewClient(apiKey)
if err != nil {
	return err
}
points, err := client.GetTimeSeries(ctx, "market/price_usd_close", &glassnode.MetricParams{
	Asset:    "BTC",
	Interval: "24h",
})

Timestamps are Unix seconds, and missing values are nil pointers. Methods such as GetTimeSeries, GetObjectTimeSeries and GetBulkMetric cover the common response shapes; GetMetric, Get and Raw handle everything else.

The package reads no environment variables or files: all configuration, including credentials, is passed to NewClient as options. Errors can be inspected with errors.As for APIError, InputError, TransportError, DecodeError and AuthError.

Index

Examples

Constants

View Source
const DefaultBaseURL = "https://api.glassnode.com"

DefaultBaseURL is the standard Glassnode API endpoint.

Variables

View Source
var ErrResponseTooLarge = errors.New("response exceeds the configured size limit")

ErrResponseTooLarge is the cause of every ResponseTooLargeError, for errors.Is.

Functions

This section is empty.

Types

type APIAddon

type APIAddon struct {
	Value  int             `json:"value"`
	Period AllowancePeriod `json:"period,omitempty"`
	RPM    int             `json:"rpm,omitempty"`
}

APIAddon is an API allowance returned by the usage endpoint: Value units per Period, at most RPM requests per minute when the API reports it.

type APIError

type APIError struct {
	StatusCode int
	Endpoint   string
	Detail     string
	RetryAfter time.Duration
}

APIError describes a non-2xx response. Detail is bounded and credential-redacted. RetryAfter is how long the server asked the client to wait, taken from the Retry-After header or, for 429 responses, from x-rate-limit-reset. It is zero when the server gave no such hint.

func (*APIError) Error

func (e *APIError) Error() string

func (*APIError) Retryable

func (e *APIError) Retryable() bool

Retryable reports whether this status is eligible for a GET retry.

type APIUsage

type APIUsage struct {
	CreditsUsed       int        `json:"creditsUsed"`
	DailyRequestsUsed int        `json:"dailyRequestsUsed"`
	APIAddons         []APIAddon `json:"apiAddons"`
}

APIUsage reports usage and subscribed API allowances. CreditsUsed counts credits this month and DailyRequestsUsed counts requests today; each is the counter for an allowance of the matching period.

func (*APIUsage) Allowance added in v0.2.0

func (u *APIUsage) Allowance() (allowance Allowance, ok bool)

Allowance returns the account's allowance with the usage of the matching period. ok is false when the account has no add-on, an add-on reports a period the client does not know, or add-ons of different periods are combined, since no single counter then applies; callers should not guess.

func (*APIUsage) CreditsPerMonth deprecated

func (u *APIUsage) CreditsPerMonth() int

CreditsPerMonth returns the largest subscribed allowance, or zero, whatever its period.

Deprecated: an allowance may be daily; use Allowance, which reports the period and the usage counted against it.

func (*APIUsage) UnmarshalJSON

func (u *APIUsage) UnmarshalJSON(data []byte) error

UnmarshalJSON requires creditsUsed and tolerates missing add-ons.

type Allowance added in v0.2.0

type Allowance struct {
	Limit  int
	Period AllowancePeriod
	Used   int
}

Allowance is an account's API allowance and the usage counted against it. On a daily allowance the unit is requests and Used is today's requests; on a monthly allowance the unit is credits and Used is this month's credits.

func (Allowance) Remaining added in v0.2.0

func (a Allowance) Remaining() int

Remaining returns how much of the allowance is left in the current period, never below zero.

type AllowancePeriod added in v0.2.0

type AllowancePeriod string

AllowancePeriod is the period an API allowance is granted over.

const (
	AllowanceDaily   AllowancePeriod = "daily"
	AllowanceMonthly AllowancePeriod = "monthly"
)

Allowance periods reported by the usage endpoint. An add-on without a period predates the field and is monthly.

type Asset

type Asset struct {
	ID             string            `json:"id"`
	ExternalIDs    map[string]string `json:"external_ids,omitempty"`
	Symbol         string            `json:"symbol"`
	Name           string            `json:"name"`
	AssetType      string            `json:"asset_type"`
	Blockchains    []Blockchain      `json:"blockchains"`
	Categories     []string          `json:"categories,omitempty"`
	LogoURL        string            `json:"logo_url,omitempty"`
	SemanticTags   []string          `json:"semantic_tags,omitempty"`
	DefaultNetwork string            `json:"default_network,omitempty"`
}

Asset describes a supported blockchain asset or token.

type AssetsResponse

type AssetsResponse struct {
	Data []Asset `json:"data"`
}

AssetsResponse is the wire envelope for asset metadata.

type AuthError

type AuthError struct{ Err error }

AuthError describes a token-source failure or an invalid token. It is never retried. Messages redact credentials used in the call; the token source must avoid returning errors containing other credentials unknown to the SDK. Unwrapped causes may contain secrets and should not be logged indiscriminately.

func (*AuthError) Error

func (e *AuthError) Error() string

func (*AuthError) Unwrap

func (e *AuthError) Unwrap() error

type Blockchain

type Blockchain struct {
	Blockchain     string `json:"blockchain"`
	Address        string `json:"address,omitempty"`
	Decimals       int    `json:"decimals,omitempty"`
	OnChainSupport bool   `json:"on_chain_support"`
}

Blockchain describes a token deployment and on-chain support.

type BulkDataPoint

type BulkDataPoint struct {
	Timestamp int64       `json:"t"`
	Bulk      []BulkEntry `json:"bulk"`
}

BulkDataPoint groups asset values at a Unix timestamp in seconds.

func (*BulkDataPoint) UnmarshalJSON

func (p *BulkDataPoint) UnmarshalJSON(data []byte) error

UnmarshalJSON requires the timestamp and bulk entries.

type BulkEntry

type BulkEntry struct {
	Value  *float64
	Params map[string]string
}

BulkEntry is one value of a bulk response. Params holds every selector that identifies the entry, such as "a", "e", "network" or, for object metrics, "category"; which selectors appear depends on the metric. Asset and Network read the common ones.

Selector values are strings in the API. Should a selector arrive as another JSON type, Params holds its JSON text (5 becomes "5"); use GetMetric with your own type when exact types matter.

func (BulkEntry) Asset

func (p BulkEntry) Asset() string

Asset returns the "a" selector, or "" for a metric without one.

func (BulkEntry) MarshalJSON

func (p BulkEntry) MarshalJSON() ([]byte, error)

MarshalJSON encodes the entry with the selectors next to "v", as the API does. Every selector is written as a JSON string, since Params cannot tell a numeric selector from an asset such as "1".

func (BulkEntry) Network

func (p BulkEntry) Network() string

Network returns the "network" selector, or "" when the entry has none.

func (*BulkEntry) UnmarshalJSON

func (p *BulkEntry) UnmarshalJSON(data []byte) error

UnmarshalJSON requires v and keeps every other field as a selector.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client calls the Glassnode API. Its configuration is immutable after construction and it is safe for concurrent use.

func NewClient

func NewClient(apiKey string, options ...Option) (*Client, error)

NewClient constructs a client with header API-key authentication, a one-minute timeout per attempt and two GET retries. Configure exactly one of an API key, WithBearerToken or WithTokenSource. Explicit WithTimeout overrides a supplied HTTP client timeout regardless of option order; other options apply in order.

func (*Client) Get

func (c *Client) Get(ctx context.Context, endpoint string, params url.Values, dst any) error

Get decodes a GET response into dst. Use a non-nil pointer (including *json.RawMessage). Dynamic values decode as json.Number rather than float64. Custom UnmarshalJSON methods allow application-specific validation.

The response is read completely, with retries, before anything is decoded, so dst is written to at most once, from a successful attempt. A failed request or invalid JSON leaves dst untouched; a type mismatch may leave it partially filled, as json.Unmarshal does.

func (*Client) GetAPIUsage

func (c *Client) GetAPIUsage(ctx context.Context) (*APIUsage, error)

GetAPIUsage fetches the current authenticated user's API usage.

func (*Client) GetBulkMetric

func (c *Client) GetBulkMetric(ctx context.Context, path string, params *MetricParams) ([]BulkDataPoint, error)

GetBulkMetric fetches the bulk variant of a metric and unwraps the data envelope. Pass the base metric path, without a /bulk suffix. The API requires Since and limits the time range per request (31 days at 24h resolution). Each asset and selector combination is billed like a separate request, and omitting Assets selects every asset, so set the selectors explicitly.

func (*Client) GetMetric

func (c *Client) GetMetric(ctx context.Context, path string, params *MetricParams, dst any) error

GetMetric decodes a metric response into dst. Use this for custom/nested shapes or lossless json.RawMessage; common shapes have convenience methods.

func (*Client) GetMetricCSV

func (c *Client) GetMetricCSV(ctx context.Context, path string, params *MetricParams, w io.Writer) error

GetMetricCSV requests a metric in CSV and copies the response to w as it arrives, without decoding it. The columns are the API's: timestamp and value, the object keys for object metrics, plus computed_at for point-in-time metrics. Bulk metrics are not available in CSV.

Failures before any byte reaches w (transport errors, 429, 5xx, a connection lost right after the headers) are retried as usual. A failure after output has been written is not, since a retry would duplicate it; neither is a body over WithMaxResponseBytes. An error from w itself is returned wrapped, so errors.Is against it works, and is never retried.

The per-attempt timeout (one minute by default) covers reading the whole body. For a large download over a slow link, raise it with WithTimeout or disable it with WithTimeout(0) and bound the call with a context deadline; a timeout in mid-body is reported as a TransportError noting that partial output was written.

func (*Client) GetMetricMetadata

func (c *Client) GetMetricMetadata(ctx context.Context, path string, params *MetricParams) (*MetricMetadata, error)

GetMetricMetadata describes a metric's selectors, variants and availability.

func (*Client) GetMetricStats

func (c *Client) GetMetricStats(ctx context.Context, path string, params *MetricParams) (*MetricStats, error)

GetMetricStats fetches metric data-lag percentiles.

func (*Client) GetObjectTimeSeries

func (c *Client) GetObjectTimeSeries(ctx context.Context, path string, params *MetricParams) ([]ObjectTimeSeriesPoint, error)

GetObjectTimeSeries fetches a metric whose o field is a numeric breakdown.

func (*Client) GetTimeSeries

func (c *Client) GetTimeSeries(ctx context.Context, path string, params *MetricParams) ([]TimeSeriesPoint, error)

GetTimeSeries fetches a scalar metric with nullable values.

Example
package main

import (
	"context"
	"fmt"
	"net/http"
	"net/http/httptest"
	"time"

	glassnode "github.com/glassnode/glassnode-api-go-client"
)

func main() {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, `[{"t":1700000000,"v":42000},{"t":1700086400,"v":null}]`)
	}))
	defer server.Close()
	client, err := glassnode.NewClient("example-key", glassnode.WithBaseURL(server.URL))
	if err != nil {
		panic(err)
	}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	points, err := client.GetTimeSeries(ctx, "market/price_usd_close", &glassnode.MetricParams{Asset: "BTC"})
	if err != nil {
		panic(err)
	}
	for _, point := range points {
		if point.Value == nil {
			fmt.Println("gap")
		} else {
			fmt.Printf("%.0f\n", *point.Value)
		}
	}
}
Output:
42000
gap

func (*Client) ListAssetBlockchains

func (c *Client) ListAssetBlockchains(ctx context.Context, filter string) ([]string, error)

ListAssetBlockchains lists asset blockchains, optionally scoped by a CEL filter.

func (*Client) ListAssetCategories

func (c *Client) ListAssetCategories(ctx context.Context, filter string) ([]string, error)

ListAssetCategories lists asset categories, optionally scoped by a CEL filter.

func (*Client) ListAssetTags

func (c *Client) ListAssetTags(ctx context.Context, filter string) ([]string, error)

ListAssetTags lists asset tags, optionally scoped by a CEL filter.

func (*Client) ListAssets

func (c *Client) ListAssets(ctx context.Context, filter string) ([]Asset, error)

ListAssets lists asset metadata, optionally scoped by a CEL filter.

func (*Client) ListExchanges

func (c *Client) ListExchanges(ctx context.Context) ([]string, error)

ListExchanges lists the supported exchanges.

func (*Client) ListMetricTags

func (c *Client) ListMetricTags(ctx context.Context) ([]string, error)

ListMetricTags lists the available metric tags.

func (*Client) ListMetrics

func (c *Client) ListMetrics(ctx context.Context, params *MetricParams) ([]string, error)

ListMetrics lists metric paths, optionally filtered by asset and other selectors.

func (*Client) ListMiners

func (c *Client) ListMiners(ctx context.Context) ([]string, error)

ListMiners lists the supported miners.

func (*Client) ListNames

func (c *Client) ListNames(ctx context.Context, endpoint, filter string) ([]string, error)

ListNames lists a named metadata endpoint, optionally filtered by CEL.

func (*Client) ListNetworks

func (c *Client) ListNetworks(ctx context.Context) ([]string, error)

ListNetworks lists the supported networks.

func (*Client) Raw

func (c *Client) Raw(ctx context.Context, endpoint string, params url.Values) ([]byte, error)

Raw calls a GET endpoint and returns its successful response bytes. It is an escape hatch for new endpoints; it does not decode or validate response JSON. Query maps are copied and reserved authentication parameters are rejected.

type DecodeError

type DecodeError struct {
	Endpoint string
	Err      error
}

DecodeError describes a response that does not match the destination Go type. It is never retried. SDK-generated messages redact credentials, including custom decoder errors. Unwrap exposes the original error for inspection.

func (*DecodeError) Error

func (e *DecodeError) Error() string

func (*DecodeError) Unwrap

func (e *DecodeError) Unwrap() error

type InputError

type InputError struct{ Field, Message string }

InputError describes invalid configuration or arguments, before any request.

func (*InputError) Error

func (e *InputError) Error() string

type LagPercentiles

type LagPercentiles struct {
	P50 *float64 `json:"p50,omitempty"`
	P90 *float64 `json:"p90,omitempty"`
	P95 *float64 `json:"p95,omitempty"`
	P99 *float64 `json:"p99,omitempty"`
}

LagPercentiles are durations in the enclosing MetricLagEntry.Unit. Pointers distinguish missing percentiles from measurements of zero.

type MetricDescriptors

type MetricDescriptors struct {
	Name             string            `json:"name,omitempty"`
	ShortName        string            `json:"short_name,omitempty"`
	Group            string            `json:"group,omitempty"`
	Tags             []string          `json:"tags,omitempty"`
	Description      map[string]string `json:"description,omitempty"`
	DataSharingGroup string            `json:"data_sharing_group,omitempty"`
}

MetricDescriptors contains human-readable metric descriptions.

type MetricLagEntry

type MetricLagEntry struct {
	Unit       string                    `json:"unit"`
	Window     string                    `json:"window"`
	Resolution map[string]LagPercentiles `json:"resolution"`
}

MetricLagEntry contains data lag over a measurement window by resolution.

type MetricMetadata

type MetricMetadata struct {
	Path               string              `json:"path,omitempty"`
	Tier               int                 `json:"tier,omitempty"`
	IsPIT              bool                `json:"is_pit,omitempty"`
	Parameters         map[string][]string `json:"parameters"`
	ParametersDefaults map[string][]string `json:"parameters_defaults,omitempty"`
	Queried            map[string]string   `json:"queried,omitempty"`
	Refs               Refs                `json:"refs,omitempty"`
	BulkSupported      bool                `json:"bulk_supported"`
	TimeRange          *TimeRange          `json:"timerange,omitempty"`
	Modified           int64               `json:"modified,omitempty"`
	Descriptors        *MetricDescriptors  `json:"descriptors,omitempty"`
}

MetricMetadata describes a metric, its selectors and available variants.

func (*MetricMetadata) UnmarshalJSON

func (m *MetricMetadata) UnmarshalJSON(data []byte) error

UnmarshalJSON accepts each parameters_defaults value either as a list, as the API currently returns it, or as a single string, as the API documentation describes it.

type MetricParams

type MetricParams struct {
	Asset     string
	Assets    []string
	Exchanges []string
	Since     time.Time
	Until     time.Time
	Interval  string
	Currency  string
	Extra     url.Values
}

MetricParams selects data or filters metadata. Zero fields are omitted. Asset is a convenience for one asset; Assets and Exchanges encode repeated query parameters (a=BTC&a=ETH). Do not set both Asset and Assets. Extra accepts additional documented selectors such as network, quote_symbol, bps, side, size, miner and maturity; it must not duplicate a typed field.

func (*MetricParams) Values

func (p *MetricParams) Values() (url.Values, error)

Values returns a fresh query map. Unix seconds may also be supplied through Extra["s"] and Extra["u"] when the corresponding time.Time field is zero.

type MetricStats

type MetricStats struct {
	Lag []MetricLagEntry `json:"lag"`
}

MetricStats contains the API's lag statistics. Lag values are durations, not timestamps; use each entry's Unit when interpreting them.

type MetricVariant

type MetricVariant struct {
	Base *string `json:"base,omitempty"`
	Bulk *string `json:"bulk,omitempty"`
	PIT  *string `json:"pit,omitempty"`
}

MetricVariant links the base, bulk and point-in-time metric paths.

type NameEntry

type NameEntry struct {
	Name string `json:"name"`
}

NameEntry is a single named value in a names response.

type NamesResponse

type NamesResponse struct {
	Data []NameEntry `json:"data"`
}

NamesResponse is the response of the metadata list endpoints (/v1/metadata/tags, /v1/metadata/assets/tags, ...): {"data":[{"name":"..."},...]}.

type ObjectTimeSeriesPoint

type ObjectTimeSeriesPoint struct {
	Timestamp  int64               `json:"t"`
	Object     map[string]*float64 `json:"o"`
	ComputedAt *int64              `json:"computed_at,omitempty"`
}

ObjectTimeSeriesPoint is an object metric point (OHLC or a breakdown). Object values are nullable; nested shapes can be decoded with GetMetric. ComputedAt is set for point-in-time metrics, as in TimeSeriesPoint.

func (*ObjectTimeSeriesPoint) UnmarshalJSON

func (p *ObjectTimeSeriesPoint) UnmarshalJSON(data []byte) error

UnmarshalJSON requires the timestamp and object, tolerating new fields.

type Option

type Option func(*Client) error

Option configures a Client at construction time.

func WithAPIKeyInQuery

func WithAPIKeyInQuery() Option

WithAPIKeyInQuery sends api_key in the URL instead of X-Api-Key. Prefer the default header authentication to keep credentials out of proxy/access logs.

func WithBaseURL

func WithBaseURL(raw string) Option

WithBaseURL selects an API origin, optionally with a path prefix. Credentials, query strings and fragments are forbidden. HTTP is allowed for local testing.

func WithBearerToken

func WithBearerToken(token string) Option

WithBearerToken uses an existing OAuth access token. Pass an empty API key to NewClient. For refreshable tokens, use WithTokenSource instead.

func WithHTTPClient

func WithHTTPClient(client *http.Client) Option

WithHTTPClient uses a copy of the supplied client's configuration. Its transport and jar remain shared. Redirects are always disabled to prevent credential forwarding. Configure the transport before sharing the client.

func WithMaxResponseBytes

func WithMaxResponseBytes(limit int64) Option

WithMaxResponseBytes rejects response bodies larger than limit with a ResponseTooLargeError instead of decoding them. The default, zero, is no limit, as the API's full-history responses can legitimately be large. Use it to bound memory where a failed call is preferable to an unbounded one.

func WithRetryPolicy

func WithRetryPolicy(policy RetryPolicy) Option

WithRetryPolicy replaces the default two retries with full-jitter backoff from one second to 65 seconds, which covers the API's one-minute rate-limit window. Delays must be positive when enabled.

func WithTimeout

func WithTimeout(timeout time.Duration) Option

WithTimeout sets the per-attempt HTTP timeout. Zero disables it. Use a context deadline to bound the entire operation, including all retries and waits. This overrides WithHTTPClient's timeout regardless of option order.

func WithTokenSource

func WithTokenSource(source TokenSource) Option

WithTokenSource uses OAuth tokens supplied at request time. Pass an empty API key to NewClient. Each token is redacted from that call's error messages.

func WithUserAgent

func WithUserAgent(agent string) Option

WithUserAgent identifies the calling application. The SDK's default is glassnode-api-go-client. A blank value or one containing control characters is rejected.

type Refs

type Refs struct {
	Docs          string         `json:"docs,omitempty"`
	Studio        string         `json:"studio,omitempty"`
	MetricVariant *MetricVariant `json:"metric_variant,omitempty"`
}

Refs links API documentation, Studio and related metric variants.

type ResponseTooLargeError

type ResponseTooLargeError struct {
	Endpoint string
	Limit    int64
}

ResponseTooLargeError reports a successful response whose body exceeds the WithMaxResponseBytes limit. It is a decision of the client's configuration, not a transport or decoding failure, and the call is not retried.

func (*ResponseTooLargeError) Error

func (e *ResponseTooLargeError) Error() string

func (*ResponseTooLargeError) Unwrap

func (e *ResponseTooLargeError) Unwrap() error

Unwrap returns ErrResponseTooLarge.

type RetryPolicy

type RetryPolicy struct {
	MaxRetries int
	BaseDelay  time.Duration
	MaxDelay   time.Duration
}

RetryPolicy controls GET retries. MaxRetries excludes the initial attempt. Retry-After is a minimum delay; a value above MaxDelay stops retries rather than retrying before the server permits it. Zero MaxRetries disables retries.

type TimeRange

type TimeRange struct {
	Min int64 `json:"min,omitempty"`
	Max int64 `json:"max,omitempty"`
}

TimeRange bounds available data in Unix seconds.

type TimeSeriesPoint

type TimeSeriesPoint struct {
	Timestamp  int64    `json:"t"`
	Value      *float64 `json:"v"`
	ComputedAt *int64   `json:"computed_at,omitempty"`
}

TimeSeriesPoint is a scalar metric point. Value is nil for a gap (JSON null). Timestamp is Unix seconds, not milliseconds. ComputedAt is the Unix time at which a point-in-time metric computed the value; it is nil for other metrics.

func (*TimeSeriesPoint) UnmarshalJSON

func (p *TimeSeriesPoint) UnmarshalJSON(data []byte) error

UnmarshalJSON requires the timestamp and scalar value, tolerating new fields.

type TokenRefresher

type TokenRefresher interface {
	TokenSource
	Refresh(ctx context.Context) (string, error)
}

TokenRefresher is a TokenSource that can replace a token the API rejected. When a request gets a 401, the client calls Refresh once and repeats the request with the new token if it differs from the rejected one; a second 401 is returned to the caller. Returning the same token means nothing newer exists, and the 401 is returned as is. Refresh errors and an empty or malformed token are reported as AuthError. Concurrent calls rejected with the same token share one Refresh.

type TokenSource

type TokenSource interface {
	Token(ctx context.Context) (string, error)
}

TokenSource supplies an OAuth access token for each HTTP attempt. Implementations own refresh and storage, must honor ctx and must be safe for concurrent calls. Token-source errors are never retried. A 401 response is returned as is unless the source also implements TokenRefresher.

type TokenSourceFunc

type TokenSourceFunc func(context.Context) (string, error)

TokenSourceFunc adapts a function to TokenSource.

func (TokenSourceFunc) Token

func (f TokenSourceFunc) Token(ctx context.Context) (string, error)

Token calls f with the request context.

type TransportError

type TransportError struct {
	Endpoint string
	Err      error
}

TransportError describes a failure in transit. SDK-generated error messages include the credential-redacted cause. Unwrap retains the original cause. The cause may contain credentials and should not be logged indiscriminately.

func (*TransportError) Error

func (e *TransportError) Error() string

func (*TransportError) Unwrap

func (e *TransportError) Unwrap() error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL