Repository navigation
Releases: glassnode/glassnode-api-ts-client
Release list
v1.0.0
1.0.0 is the first stable release: from here on the public API follows semver, as the README's
Stability and versioning
section defines. Breaking changes: deprecated exports removed, lenient MetricMetadata fields,
modified as unix seconds, no browser field, maxRetries defaulting to 2 and Node.js >= 22;
each has migration notes below.
It also contains 0.29.4–0.30.1. Of those, only 0.30.1 reached npm: 0.29.4, 0.29.5 and 0.30.0 were
never published and have no GitHub Release. If you are upgrading from 0.29.3 or earlier, read their
sections in the full
CHANGELOG too
(notably 0.30.0's BulkEntry['v'] type change).
Breaking changes
-
Removed the deprecated exports
MetricTierSchema,MetricTier,MetricDataTypeSchema,
MetricDataTypeandFetchFn(#23). None of them was used by the client; they were deprecated
with a promise of removal in 1.0. Migration:MetricTier/MetricTierSchema: useMetricMetadata['tier'], anumber(e.g.2). The
string enum ('free' | 'tier1' | …) never matched the API'stierfield.MetricDataType/MetricDataTypeSchema: define your own enum if you need these values
('average' | 'sum' | 'count' | 'percentage' | 'ratio'); no response was ever validated
against them.FetchFn: useGlassnodeFetch, the type of thefetchconfig option, ortypeof fetch
(whichFetchFnwas an alias of; a standardfetchstill fits the option).
-
MetricMetadata(fromgetMetricMetadata()/MetricMetadataSchema):refs,queriedand
parametersare now optional, in line with the lenient response policy (0.12.0) (#25). A response
that omits any of them now parses instead of rejecting the whole call; onlypathandtier
stay required. An absent field is reported as sent,undefined, with no{}default. Their
types become… | undefined, which breaks code that reads them directly (e.g.
meta.refs.docsorObject.keys(meta.parameters)) understrictNullChecks. The recorded API
responses still carry all three, so runtime values do not change today.Migration: read these fields with
?.and a fallback where you need one, e.g.
meta.refs?.docs,meta.queried?.a,meta.parameters?.a ?? [],
Object.entries(meta.parameters ?? {}). -
MetricMetadata.modifiedis now unix seconds (number | undefined), passed through as the
API sends it, like every other time field (timerange.min/max, the time series and bulkt,
callMetric()results). It used to be the one field converted to aDate. The schema is now
z.number().optional(); README "Timestamps", the schema comments and
examples/ex.metadata.validation.tsare updated. NotoDatehelper is added:
new Date(t * 1000)already covers every field (#22).-
Behaviour change:
modified: 0now passes through as0; it used to becomeundefined
("no modification time recorded"). Absent is stillundefined. -
Migration: convert explicitly where you need a
Date:const modified = meta.modified !== undefined ? new Date(meta.modified * 1000) : undefined;
To keep treating
0as "not recorded", usemeta.modified || undefined(or check for0)
before converting.
-
-
package.jsonno longer has a top-levelbrowserfield;unpkgandjsdelivrfields point at
dist/glassnode-api.umd.min.jsinstead (#37).exportsgets nobrowsercondition, so
exports-aware tools (Node, webpack 5, Vite, esbuild, Rollup, TypeScript) resolve exactly as
before: the tree-shakeable ESM build (import) or CommonJS (require). Both bundles still ship
at the same paths.- CDNs: the bare
https://unpkg.com/glassnode-apiURL now serves the UMD bundle. unpkg
ignoresbrowser, so it used to serve the CommonJSmain(dist/index.js), which fails in a
<script>tag. jsDelivr already served the UMD bundle throughbrowserand still does,
throughjsdelivr. Explicitdist/…min.jsURLs are unchanged. - Who is affected: tools that read
browserand ignoreexports, chiefly Browserify
(or a bundler withexportsresolution turned off). Browserify now bundlesdist/index.jsplus
zod's CommonJS build instead of the UMD bundle. It still works, with the same API, but the
output is about 6× larger: about 186 KB gzipped instead of 31 KB. - Migration: to keep the smaller bundle in Browserify, require the UMD file by path,
require('glassnode-api/dist/glassnode-api.umd.min.js'), or mapglassnode-apito it (e.g.
with abrowserfield in your ownpackage.json). Browserify ignoresexports, so the deep
path resolves;exports-aware tools cannot import it, and do not need to. In a page, load it
with a<script>tag from a CDN or your own copy. - webpack 4 is not affected: it could not parse the package before this change (the UMD bundle
uses?.) and still cannot (the ESM build targets ES2022). It needsnode_modules
transpiled either way.
- CDNs: the bare
-
maxRetriesnow defaults to2(was0) (#49). A429, a5xxor a transport failure
(network error, per-attempttimeout) is retried up to twice (up to 3 attempts), with the
existing backoff: exponential fromretryDelay(1 s), capped atmaxRetryDelay(30 s), full
jitter, aRetry-Afterhonoured. Every client call is aGET, so a retry repeats no side
effect. TheGlassnodeAPIconstructor applies the default (it depends onx402), exported as
DEFAULT_MAX_RETRIES(2) andDEFAULT_X402_MAX_RETRIES(0).GlassnodeConfigSchema
stays an object schema but no longer fills inmaxRetries:parse()leaves an unset value
undefined(it was0), and its output type is nownumber | undefined. Resolve it with
?? DEFAULT_MAX_RETRIES(orDEFAULT_X402_MAX_RETRIESwithx402).
onRequest/onResponsehook events reportmaxAttempts: 3by default.- Behaviour change: a call that used to fail at once on a transient error may now succeed,
or fail only after up to two waits; the error is the last attempt's.onRetryhooks and the
loggernow fire on those retries. - Worst-case latency:
timeoutis per attempt, so withtimeoutset a failing call can now
take about 3 ×timeoutplus the backoff. The backoff is at most about 3 s with the defaults
(jittered, up to 1 s then 2 s). ARetry-Afterwait replaces it, capped atmaxRetryDelay
(30 s by default, so up to about 60 s over two retries). For a deadline on the whole call,
retries included, passsignal: AbortSignal.timeout(ms)(see README
"Cancellation and per-call timeouts"),
or lowermaxRetries/maxRetryDelay. - x402 mode keeps
0: withx402: truethe default stays0. The fetch from
createX402Fetchnever lets a failure after a signed payment be retried (it raises
GlassnodePaymentError), but the client cannot tell whether a caller-supplied payment fetch
does the same, and a retry of a paid5xxor timeout through a bare x402 wrapper would sign a
new payment and could pay twice. WithcreateX402Fetchyou can opt in (maxRetries: 2): only
unpaid attempts are ever retried. - Opt out: pass
maxRetries: 0for the previous single-attempt behaviour.
- Behaviour change: a call that used to fail at once on a transient error may now succeed,
-
Node.js >= 22 is now required (
engines.nodeis>=22.0.0, was>=18.0.0) (#48). Node 18
reached end-of-life in April 2025 and Node 20 in April 2026; Node 22 is in maintenance until
April 2027.@types/nodemoves to the new floor (^22), so the compiler still rejects APIs newer
than the oldest supported Node. The CI floor jobcompat-node18becomescompat-node-floor
and runs on Node 22 (same steps: build, CJSrequiresmoke,scripts/smoke-timeout.mjs). No
code or output changes: thetsconfig*.jsontarget/libare unchanged (the Node builds'
ES2022 already fits Node 22, and their ESM output also reaches browsers through bundlers; the
browser bundles' own code stays ES2015, while their bundled Zod is ES2020), and the client keeps
its ownAbortSignal.any()stand-in for older browsers.Migration: upgrade to Node.js 22 or later. On Node 18 or 20, stay on 0.x: package managers
that enforceengines(e.g. withengine-strict) refuse to install 1.0, and it is not tested
there.
Docs
- README: a new "Stability and versioning" section states what semver covers from 1.0: the public
API, what a minor or a major release may change (including widened output types, rejected
inputs, Zod and optional peer majors), how new response fields are parsed, the TypeScript and
browser baselines, and what is not covered. The Features
list no longer calls retries opt-in: they are on by default since themaxRetrieschange above.
Build
tsconfig.browser.jsonusesmodule: ESNextandmoduleResolution: bundlerinstead of the
deprecatedmoduleResolution: node(node10), sobuild:browserno longer warns TS5107 and
keeps working on TypeScript 7 (#35). The browser bundles are byte-identical before and after.
Tooling
No change to the published package (#50).
- Dev dependencies, within their current majors and the
.npmrc7-dayminimum-release-age:
vitestand@vitest/coverage-v85.0.1,eslint10.11.0,prettier3.9.8,rollup4.63.4,
typescript-eslint8.70.1, the@x402/evm/@x402/fetchdev copies 2.27.0 andviem2.56.8.
TypeScript stays 6.0.3 (#39).examples/:@x402/*2.27.0,viem2.56.8 anddotenv16.6.1
(still 16.x; the 17/18 majors are not taken), locked withnpm install --before=<7 days ago>.
pnpm auditandnpm audit(inexamples/) report no vulnerabilities. - CI: every GitHub Action is pinned by full com...
v0.30.1
- Fix:
callBulkMetric()now rejects ametricPathending in/bulk(e.g. the metadata's
refs.metric_variant.bulk,/market/marketcap_usd/bulk) with aGlassnodeInputError
(argument: 'metricPath') before any request, telling you to pass the base path
(/market/marketcap_usd). It appends/bulkitself, so such a path used to request
…/bulk/bulkand fail with a confusing 404GlassnodeApiError. The path is rejected, not
silently rewritten, like other malformed paths.callMetric()with a/bulkpath is unchanged.
ThecallBulkMetricdoc comment and the README's Bulk Metrics section say to pass the base path.
v0.29.3
- Package metadata:
package.jsonauthor.urlnow points at the author's GitHub profile
(https://github.com/planadecu) instead of the oldplanadecu/glassnode-api-noderepository. - Examples:
examples/.npmrcnow says accurately that it coversignore-scriptsonly (npm ignores
the root's pnpm-onlyminimum-release-age) and how to apply the 7-day rule with npm
(npm install --before=<date>).examples/README.mdrecommendsnpm ci, as CI runs, notes that
install scripts are disabled, and shows how to add or update a dependency with--before. - Docs:
CLAUDE.mdnow states thatmainis protected by a ruleset. No code change.
v0.29.2
- License:
LICENSEis now the official Apache License 2.0 text, verbatim from
https://www.apache.org/licenses/LICENSE-2.0.txt. The previous file was a paraphrase (for example,
§4 was reworded and §9's indemnity clause was missing). The copyright lines sit in the
appendix's boilerplate notice, and nothing else differs from the official text. - License: the Glassnode entity is now named correctly as Glassnode AG, the Swiss company, in
LICENSE,NOTICE,package.jsoncontributorsand the 0.29.0 entry below. No code change.