Skip to content

feat(reader): exportAddressBook — multi-network address-book / typed-client export (#152) - #162

Merged
robercano-ghbot merged 1 commit into
mainfrom
feat/issue-152-reader-address-book
Jul 21, 2026
Merged

feat(reader): exportAddressBook — multi-network address-book / typed-client export (#152)#162
robercano-ghbot merged 1 commit into
mainfrom
feat/issue-152-reader-address-book

Conversation

@robercano-ghbot

Copy link
Copy Markdown
Collaborator

What

Closes #152.

Adds exportAddressBook to @redeploy/reader: aggregates one or more DeploymentSnapshots into a canonical downstream artifact so reDeploy is the source of truth for "where is everything deployed".

Output:

  • json — deterministic address book keyed chainId -> contractId -> { address, contractName, chainId, network?, deployedAt, abi? }.
  • ts — a typed TypeScript module using as const, so addresses[chainId].MyContract.address is a type-safe lookup (verified by a real tsc --noEmit compile in the tests).
  • dts — matching declaration mirror for consumers of compiled output.
  • packageFiles (optional, when packageName is set) — a publishable package scaffold (package.json + index.js + index.d.ts) for teams that version their address book on npm.
  • warnings — surfaced for skipped/conflicting entries.

Per-contract ABIs supplied via abis (contractName -> ABI) are embedded verbatim (viem-ready); omitted entirely when not provided.

Behavior

  • Deterministic (diffs cleanly in git): chainId keys numeric-ascending, contractId keys sorted, fixed per-entry field order, trailing newline. Building twice is byte-identical.
  • Multiple networks: two snapshots of the same spec on two chainIds -> one artifact with both chainIds (the acceptance scenario, covered by a test).
  • Null-address contracts: excluded from the book with a warning.
  • Conflicting address for the same (chainId, contractId): first-wins with a warning; identical duplicates are silent.
  • Empty input: valid empty artifact, not an error.

Scope is confined to packages/reader/ (module boundary respected). Pure/read-only — the caller persists the output.

Gates

  • build / lint / typecheck: pass
  • test: 64 passing (23 new address-book cases, incl. two real tsc --noEmit type-safety compiles)
  • coverage: 95.62% overall for @redeploy/reader; address-book.ts 97.51% stmts / 90.16% branch (threshold 80)

Review

All four lenses (correctness, tests, security, performance) approved (consensus = all).

Known low-severity follow-up (non-blocking)

The security lens noted that an own-enumerable __proto__ key inside a caller-supplied ABI (only reachable if a caller passes an ABI built via JSON.parse('{"__proto__":...}') — real viem ABIs never carry such keys) is emitted into the generated object literal and performs a prototype SET on that one nested object at module-eval time. It is confined to a single nested object in the generated artifact — no RCE, no consumer global prototype pollution. Note: simply quoting the key does NOT fix it (a quoted "__proto__" literal key still sets the prototype in JS; only a computed ["__proto__"] key creates an own property), so a proper fix would change the generated output format and warrants its own review — deferred as a follow-up rather than bundled here.

🤖 Generated with Claude Code

Aggregate one or more DeploymentSnapshots into a canonical downstream
artifact: a deterministic JSON address book plus a typed TypeScript
module (as const, so addresses[chainId].MyContract is type-safe), a
matching .d.ts, and an optional publishable package scaffold. Optional
per-contract ABIs are embedded verbatim (viem-ready) when supplied.

Output is deterministic (chainId numeric asc, contractId sorted, fixed
field order, trailing newline) so the artifact diffs cleanly in git.
Null-address contracts are skipped with a warning; conflicting addresses
for the same (chainId, contractId) are first-wins with a warning; empty
input yields a valid empty artifact.

Closes #152

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@robercano-ghbot
robercano-ghbot merged commit 4dc6494 into main Jul 21, 2026
6 checks passed
@robercano-ghbot
robercano-ghbot deleted the feat/issue-152-reader-address-book branch July 21, 2026 14:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[wave 1] reader: address-book / typed-client export (per-network addresses + ABIs artifact)

2 participants