Skip to content

blockbook-api.ts is not reproducible from typescriptify (breaks OpenAPI parity on regen) #1566

Description

@pragmaxim

Summary

blockbook-api.ts is documented as generated from Go structs (go run build/tools/typescriptify/typescriptify.go, via ManageType/Add over api.*/server.* types), but it is no longer reproducible from that tool. A fresh regen diverges from the committed file in three ways, one of which hard-breaks the OpenAPI parity check (tests/openapi/src/parity.ts, run in CI by contrib/tests/run-openapi-tests.sh). As a result, anyone adding a field to an API struct cannot safely regenerate — they must hand-edit the committed file instead.

cc @cranycrane

How this surfaced

Adding a single field to api.Address and regenerating produced a 1549-line diff and broke parity.ts with:

src/parity.ts: '"…/blockbook-api"' has no exported member named 'TxChainExtraData'. Did you mean 'TronChainExtraData'?
src/parity.ts: '"…/blockbook-api"' has no exported member named 'AccountChainExtraData'.

Root cause (three layers)

1. Hand-added named type aliases — the part that breaks parity

Commit d53b05c"feat: add ability to add chain-specific data to api.Address" (@cranycrane) — hand-edited blockbook-api.ts, replacing the generator's inline union with two named aliases:

-    chainExtraData?: { payloadType: 'tron'; payload?: TronChainExtraData } | { payloadType: string; payload?: any };
+export type TxChainExtraData = { payloadType: 'tron'; payload?: TronChainExtraData } | { payloadType: string; payload?: any };
+export type AccountChainExtraData = { payloadType: 'tron'; payload?: TronAccountExtraData } | { payloadType: string; payload?: any };
+    chainExtraData?: TxChainExtraData;
+    chainExtraData?: AccountChainExtraData;

The Go fields carry the union via a ts_type:"… | …" struct tag, and typescriptify inlines ts_type tags — it cannot emit a named export type alias. So every regen reverts these to inline unions and the named exports disappear.

Later, 8a36b41 added parity.ts, which imports Bb.TxChainExtraData / Bb.AccountChainExtraData. Because the producing hand-edit and the consuming import live in different commits, a regen silently removes symbols that a separate file depends on → CI break.

2. Indentation — cosmetic, but rewrites the entire file

build/tools/typescriptify/typescriptify.go sets t.Indent = " " (2-space), set in 15c19ac and never changed. But the committed blockbook-api.ts has always been 4-space indented (including the earliest committed version). So the committed file was always reformatted (Prettier/editor) after generation.

Consequence: a raw regen flips every nested line 4-space → 2-space. Of the 1549 changed lines, only ~81 are non-whitespace (diff -w); the rest is pure reindentation noise that hides the real changes.

3. Staleness (not parity-visible)

The committed file is also missing fields the Go structs already declare — e.g. claimedVoteReward (added to the Go Tron struct in 91c2683 but never propagated to the TS), plus a reordered ContractInfo* block. parity.ts does not catch this because its check is one-directional (TS keys must be ⊆ OpenAPI keys; OpenAPI is allowed to be wider), so a field missing from the TS slips through silently.

Note: typescriptify-golang-structs is pinned at v0.1.11 throughout history (never bumped), so this is not a dependency regression — it's accumulated manual drift on top of generator output.

Suggested fix (pick one direction)

A. Make generation authoritative again (preferred):

  • Teach the tool to emit the named TxChainExtraData / AccountChainExtraData aliases (e.g. register them via ManageType/a dedicated type instead of an inline ts_type tag), so parity.ts's imports survive a regen.
  • Make formatting deterministic: either set the tool's indentation to match the committed 4-space style, or run Prettier as a fixed post-step — so a regen is whitespace-stable.
  • Add a CI step asserting git diff --exit-code blockbook-api.ts after a fresh regen, so drift can never reappear.

B. Accept hand-maintenance: drop the named aliases and change parity.ts to compare against the inlined unions, and document that blockbook-api.ts is hand-maintained (not generated).

Either way, also resync the currently-missing fields (claimedVoteReward, etc.).

Impact / current workaround

Until fixed, do not run the generator to update blockbook-api.ts — hand-edit the committed file to mirror the Go change (matching the 4-space style and existing ts_doc text), then validate with:

cd tests/openapi && npm ci
npm run -s lint:spec && npm run -s generate && npm run -s typecheck

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions