@subsquid/pipes 1.0 is a major release: every rename is hard — the old names are removed, with no deprecated aliases — so the TypeScript compiler will point you at most of the changes. A few changes are silent, though, and those are called out below.
Pick the tab matching the version in your package.json:
- 0.1.0-beta.* — the previous 0.1.x line. Most existing pipes are here.
- 1.0.0-alpha.* — the 1.0 preview line. The pipeline structure already matches 1.0; what remains is mostly the naming overhaul that landed late in the alpha series.
beta tag, so install it explicitly:
- From 0.1.0-beta.x
- From 1.0.0-alpha.x
1. Decoders move into outputs
Portal sources became portal streams, and .pipe(decoder) / .pipeComposite({...}) on the source are gone. Pass decoders through the required outputs option instead:.pipeComposite({ ... }) is now a named record: outputs: { transfers: ..., swaps: ... }. The data shape is unchanged. See Pipe anatomy for the full 1.0 pipe structure.2. Every stream needs an id
The id shown above is now required: it must be globally unique, stable and non-empty. Targets use it as the cursor key to persist progress, and it scopes log lines and Prometheus labels. Calling .pipeTo() without one throws DefaultPipeIdError (E0001).Because cursors are now keyed by the id (previously a static "stream" key shared by every pipe), the first restart after upgrading migrates your stored cursor:If several pipes shared one offset table under the old default, pin explicit per-target ids before upgrading — see Cursor management.
3. Raw outputs are plain block arrays
If you consume a stream without a decoder,data is now the block array itself — drop the .blocks accessor (data.blocks.map(...) → data.map(...)). This also applies inside custom transformers.4. Renames
Functions:Types:
In the runner,
createDevRunner is now devRunner and each pipe’s stream field is now handler. In progress callbacks, ProgressEvent data is nested under .progress, and its state reads from/to instead of initial/last.5. Custom transformers and targets
- A transformer’s fork hook is renamed
fork→rollback— it receives the already-resolved safe cursor and must undo internal state above it. See the Transformer reference. - A custom target’s contract method is
fork(previousBlocks)→resolveFork(canonicalBlocks)— it receives the portal’s view of the canonical chain, finds the common ancestor, rolls back above it, and returns the resume cursor. See createTarget and Fork handling. query.build({ transform, fork })no longer accepts transform options — build the query first, then chain:.build().pipe({ transform, rollback }).
6. ClickHouse target
TheonRollback discriminator changed: type: 'offset_check' | 'blockchain_fork' → reason: 'recovery' | 'fork', and the context carries safeCursor only (the cursor duplicate is gone). This does not surface as a compile error if you only destructure store — grep for the old values.store.removeAllRows is now engine-aware: cancel rows (sign = -1) on CollapsingMergeTree-family tables, a lightweight DELETE (ClickHouse ≥ 23.3) elsewhere, an explicit error on Distributed tables. See the ClickHouse guide.7. Parquet target
TheTIMESTAMP_MILLIS column type is renamed TIMESTAMP (identical file format — only schemas change). New column types: DATE, JSON, STRUCT, LIST.8. Observability
- Prometheus gauges:
sqd_current_block→sqd_processed_block,sqd_last_block→sqd_end_block(the value is the end of the indexed range, not the chain head). Update dashboards and alerts. - The metrics server now serves
GET /preview/transformation(was/exemplars/transformation); the/profilerpayload keyprofilersis nowprofiles. - Upgrade Pipes UI together with the SDK — older UI versions read endpoints that no longer exist.