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
Summary
blockbook-api.tsis documented as generated from Go structs (go run build/tools/typescriptify/typescriptify.go, viaManageType/Addoverapi.*/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 bycontrib/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.Addressand regenerating produced a 1549-line diff and brokeparity.tswith: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:The Go fields carry the union via a
ts_type:"… | …"struct tag, and typescriptify inlinests_typetags — it cannot emit a namedexport typealias. So every regen reverts these to inline unions and the named exports disappear.Later, 8a36b41 added
parity.ts, which importsBb.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.gosetst.Indent = " "(2-space), set in 15c19ac and never changed. But the committedblockbook-api.tshas 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 reorderedContractInfo*block.parity.tsdoes 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-structsis 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):
TxChainExtraData/AccountChainExtraDataaliases (e.g. register them viaManageType/a dedicated type instead of an inlinets_typetag), soparity.ts's imports survive a regen.git diff --exit-code blockbook-api.tsafter a fresh regen, so drift can never reappear.B. Accept hand-maintenance: drop the named aliases and change
parity.tsto compare against the inlined unions, and document thatblockbook-api.tsis 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 existingts_doctext), then validate with: