Skip to content

@subsquid/ponder 0.17.0-sqd.1

Choose a tag to compare

@dzhelezov dzhelezov released this 20 Jul 12:49
dba6bbb

@subsquid/ponder@0.17.0-sqd.1

ponder@0.17.0 + the SQD Portal backfill layer, drop-in (bin stays ponder). This is the
first cut on ponder@0.17.0 and the newest ponder version in the fork, so it installs by
default. It carries the same Portal layer as 0.16.10-sqd.1 — the full invariant-first
re-architecture and correctness wave — grafted onto ponder@0.17.0, plus the fork-side fixes
below that landed since the last release note (0.16.8-sqd.1). It supersedes 0.16.9-sqd.1
as latest (that cut had no release note; it tracked ponder@0.16.9's upstream bytea-COPY
fix — see Compatibility).

Install: npm i @subsquid/ponder, or pin exact: npm i @subsquid/ponder@0.17.0-sqd.1.

Highlights (new since 0.16.8-sqd.1)

  • Realtime finalize is write-side idempotent on resume — no duplicated factory-child rows
    (INV-17, #175).
    A resumed single writer that re-finalizes the same factory-child creation
    block used to insert the ponder_sync.factory_addresses row twice (once by the pre-kill
    finalize transaction, once by the resume finalize — two sequential finalize transactions).
    The read→dedupe guard (read the store's persisted children, keep a child only if it is absent
    or re-discovered at a strictly lower block — LEAST semantics) previously ran only at the
    historical call site; it now also runs on the realtime finalize path, so both sync modes are
    byte-identically idempotent on resume. App data was already unaffected (the only consumer
    min-merges to a set) — this closes the store-identity/table-growth defect under repeated
    realtime crash/resume.
  • inserted.logs reports the store-inserted count, not the raw-streamed count (#143, #177).
    The inserted.logs metric (and the completion line's logs=) now counts the assembled logs
    actually written to the store, instead of the raw pre-re-match streamed count. A window whose
    over-returned logs are all re-match-dropped now reports inserted.logs=0, consistent with
    inserted.blocks=0. This is a metric-accuracy fix — no change to the data that is stored.

Portal layer

  • Write-side idempotence (portal-child-dedupe.ts, runtime/realtime.ts wiring hook): the
    shared read→dedupe core (dedupeChildAddressesAgainstStore) now runs at BOTH factory-child
    insert call sites — the historical path (portal.ts persistPendingChildren) and the
    realtime finalize path (runtime/realtime.ts handleRealtimeSyncEvent, via
    dedupeFinalizeChildAddresses), each inside its own store transaction (INV-17, #175).
  • Metrics (portal-metrics.ts, portal.ts): inserted.logs is mapped to a new
    insertedLogs counter taken from assembled.logs.length at the insertLogs site; the raw
    logs count is retained for the progress fingerprint and mb_streamed keeps raw-I/O
    semantics (#143, #177).
  • Wiring patch: portal/wiring/0.17.0.patch. It is re-derived, not verbatim: 0.16.10 → 0.17.0 is a tree-wide mechanical reformat (import-list reorder, static readonly
    static override readonly, @ts-ignore@ts-expect-error) plus dep bumps (@ponder/utils
    0.2.18 → 0.3.0, pg ^8.11 → ^8.16). Applying the 0.16.10 patch left 29 of 34 hunks landing
    by offset and 5 rejected — all 5 pure import-block additions where the reformat reordered the
    surrounding import lists; each rejected hunk's added lines were re-placed byte-for-byte into
    the reformatted import block (comm-verified: the set of added wiring lines is identical to
    0.16.10.patch, zero delta). The graft seam
    (HistoricalSync.syncBlockRangeData/syncBlockData, interval-scoped) survives untouched.

Fixes

Everything in 0.16.8-sqd.1 (the full phantom-coverage / stream-realtime+reorg / factory-and-
account-source / bounded-warmup / HTTP-client correctness wave, plus the accessList
honest-NULL fix and the default-level Portal logging), plus the two items above: INV-17
realtime-finalize write-side idempotence (#175) and the inserted.logs store-inserted metric
(#143, #177). The fork also passively inherits two off-seam upstream fixes over this range:
ponder@0.16.9's bytea-COPY encoding fix (ponder-sh/ponder#2323, in indexing-store/cache.ts)
and ponder@0.16.10's commit-path cache-invalidation resilience (runtime/isolated.ts /
multichain.ts / omnichain.ts) — both off the graft surface, inherited unchanged.

Compatibility

  • Built + tested against ponder@0.17.0. The full Portal property/regression suite is green:
    370/370 across 19 files on ponder@0.17.0 (scripts/sync-upstream.sh 0.17.0 --test) —
    and identically on every tracked version (0.15.17, 0.16.6, 0.16.7, 0.16.8, 0.16.9,
    0.16.10, 0.17.0).
  • ponder@0.17.0 bumps its build toolchain (engines.pnpm >=11, packageManager pnpm@11.0.0)
    and its deps (@ponder/utils 0.3.0, pg ^8.16); the fork inherits those upstream deps with no
    fork-side dep change. The sync-upstream.sh harness reads each clone's own packageManager and
    builds with the pnpm it declares (falling back to the historical pnpm@9.10.0 pin when the field
    is absent), so 0.16.10 still builds with pnpm 9.10.0 and 0.17.0 with pnpm 11 — both green at
    370 tests.
  • No fresh RPC byte-diff on 0.17.0; compat rests on seam-identity (the wiring patch re-derives
    but re-places every added wiring line byte-for-byte, so the graft is unchanged) plus the full
    suite, as for 0.16.10 / 0.16.9 / 0.15.17.
  • Seam verified against: 0.17.0, 0.16.10, 0.16.9, 0.16.8, 0.16.7, 0.16.6, 0.15.17
    (compat.tested). The seam is stable and identical in shape across 0.15.17 – 0.17.0.