Skip to content

Restructure TypeScript SDK as publishable npm package#43

Merged
JanKuczma merged 7 commits intomainfrom
jk-ts-support-event-mixed-data-structures
Mar 2, 2026
Merged

Restructure TypeScript SDK as publishable npm package#43
JanKuczma merged 7 commits intomainfrom
jk-ts-support-event-mixed-data-structures

Conversation

@JanKuczma
Copy link
Contributor

@JanKuczma JanKuczma commented Feb 27, 2026

Summary by CodeRabbit

  • New Features

    • Automated publish workflow to npm.
    • Type-safe contract bindings with lazy-loading.
    • New signing helpers and master-key derivation utilities.
  • Documentation

    • Added TypeScript SDK build step and expanded cleanup instructions.
  • Refactor

    • Monorepo/workspace restructure and revised package entrypoints.
    • Proof APIs simplified to single-item calls that accept block references.
  • Breaking Changes

    • Several wallet/bridge/polling helpers and exports removed or renamed; tests updated accordingly.

let notesAndData: MigrationNoteAndData<unknown>[] = [];

for (const [txHash, notes] of noteByTxHash) {
if (abiTypes.length !== notes.length) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fail for user that partially migrated already, because we're fetching all historically created migration notes. Proposed fix: do not throw an error here, just continue. On new rollup we're filtering out migrated notes, so I think it's safe to do so.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how it would fail. We're fetching all historically created migration notes along with all emitted events (so per tx, the number of notes must match the number of events must match the number of abi types). Then we filter out (using knowledge about nullifiers from the new rollup). It is something to test though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the problem would arise in the following scenario:

  • Monday: user is locking a single note via Tx A (1 note, 1 event)
  • Tuesday: user is locking two additional notes via Tx B (2 notes, 2 events)
  • Wednesday: user tries to claim Tx B notes through this interface. Frontend calls this functions, decodes Tx B, and gets abiTypes of length 2. But noteByTxHash has length 3, as it is based on all historically locked notes.

Regarding filtering - as I understand, it is done after this check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the data types in Tx B (in events) different? If not then the app/wallet should use getMigrationNotesAndData. But when an App has two entrypoints for locking notes with different MigrationData structure, and both are used in separate Txs, then neither method is suitable 🤔. Maybe getMigrationNotesAndData should "ignore" events which cannot be decoded given some abi. This way the abi would specify which MigrationNotes are fetched (and which ignored).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in #48

* Move l1 archive migration to test utils

* Publishable SDK (#46)

* reorg scopes

* npm publish ready

* publish workflow

* Update e2e-tests/test-utils.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update ts/aztec-state-migration/noir-contracts/MigrationKeyRegistry.lazy.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update ts/aztec-state-migration/noir-contracts/MigrationArchiveRegistry.lazy.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* add build step in readme

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 2, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6eee5cc and 786e0f7.

📒 Files selected for processing (1)
  • .github/workflows/publish.yml

Walkthrough

Restructures the repo into a Yarn workspace, publishes a new ts/aztec-state-migration package with typed Noir contract wrappers and lazy loaders, consolidates batch proof APIs into single-item/blockReference variants, removes bridge/polling modules (moved into e2e test utils), updates tests to package imports, and adds CI publish/build workflows.

Changes

Cohort / File(s) Summary
Monorepo & root config
package.json, tsconfig.json, .gitignore
Convert root to Yarn workspace, tighten TS emit/check settings, and remove ts/aztec-state-migration/noir-contracts from .gitignore.
CI & publish workflows, docs
.github/workflows/publish.yml, .github/workflows/ci.yml, README.md
Add npm publish workflow (version/dry_run inputs) and CI step to build TypeScript SDK; document ts SDK build and broaden clean description.
New package manifest & build infra
ts/aztec-state-migration/package.json, ts/aztec-state-migration/tsconfig.json, root package.json scripts
Add package exports map, workspace-aware scripts, package-local tsconfig, workspace-driven build/clean flow.
Contract wrappers & lazy loaders
ts/aztec-state-migration/noir-contracts/*, ts/aztec-state-migration/noir-contracts/index.ts, .../lazy.ts
Introduce full typed contract wrappers and lazy variants for MigrationKeyRegistry and MigrationArchiveRegistry and re-export them.
API surface & exports changes
ts/aztec-state-migration/index.ts, ts/aztec-state-migration/types.ts
Reduce exported surface (remove L1MigrationResult, bridge/polling exports); move deriveMasterMigrationSecretKey export source.
Key derivation & new key module
ts/aztec-state-migration/key.ts, ts/aztec-state-migration/wallet/*
Add deriveMasterMigrationSecretKey; update wallet modules to import from ../key.js and simplify entrypoint exports.
Proof API consolidation (batch → single)
ts/aztec-state-migration/proofs.ts, ts/aztec-state-migration/mode-a/proofs.ts, ts/aztec-state-migration/mode-b/proofs.ts, ts/aztec-state-migration/wallet/migration-base-wallet.ts
Convert batch proof APIs to single-item variants (e.g., buildNoteProofsbuildNoteProof), switch blockNumber→`blockReference: BlockNumber
Mode signature exports & signers
ts/aztec-state-migration/mode-a/*, ts/aztec-state-migration/mode-b/*
Add signMigrationModeA, re-export mode-b signers, remove/relocate duplicate exports and update imports/JSDoc.
Bridge & polling removal; e2e relocation
ts/aztec-state-migration/bridge.ts (removed), ts/aztec-state-migration/polling.ts (removed), e2e-tests/test-utils.ts
Remove bridge/polling modules; implement bridge/event-decoding/wait helpers and new BridgeResult shape inside e2e test utils (moved logic into tests).
E2E tests package & updates
e2e-tests/package.json, e2e-tests/*.ts, e2e-tests/test-utils.ts
Add e2e-tests package.json, update tests to import aztec-state-migration/*, adapt tests to single-proof APIs and new bridge result shape, and add helpers (deployAndFundAccount, assertEq).
Wallet entrypoints & embedded wallet changes
ts/aztec-state-migration/wallet/entrypoints/browser.ts, ts/aztec-state-migration/wallet/index.ts, ts/aztec-state-migration/wallet/migration-*.ts
Remove some embedded wallet re-exports, update imports to new key module, remove archive-proof API from wallet base, and adjust proof-related method signatures/usages.

Sequence Diagram(s)

sequenceDiagram
    participant E2E as E2E Test
    participant TU as TestUtils (bridgeBlock)
    participant L1W as L1 Wallet Client
    participant Migr as L1 Migrator Contract
    participant Inbox as L1 Inbox Contract
    participant L1RPC as L1 Node/RPC
    participant L2 as Aztec Node

    E2E->>TU: bridgeBlock(l1Wallet, l2Node, blockReference)
    TU->>L1W: send migrateArchiveRoot() tx
    L1W->>Migr: invoke L1Migrator.migrateArchiveRoot
    Migr->>L1RPC: broadcast tx
    L1RPC-->>TU: tx receipt with logs
    TU->>Inbox: decode MessageSent / ArchiveRootMigrated (extract messageHash, archiveRoot, leaf/index)
    TU->>L2: waitForL1ToL2Message(messageHash) / poll proven block
    L2-->>TU: provenBlockNumber & inclusion status
    TU-->>E2E: {provenBlockNumber, provenArchiveRoot, archiveProof, blockHeader}
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • DamianStraszak

Poem

🐰 From burrows of code the workspaces spring,

One note hops forward, proofs now single-wing,
Lazy contracts wake, their artifacts in tow,
Bridge logs hum softly as L1 seeds L2's glow,
A rabbit signs the package — npm lights the show.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.85% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Restructure TypeScript SDK as publishable npm package' directly and accurately reflects the main objectives of this changeset, which include creating workspace structure, adding package.json files, setting up npm publishing workflows, and reorganizing the TypeScript SDK.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jk-ts-support-event-mixed-data-structures

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
ts/aztec-state-migration/mode-b/signature.ts (1)

3-7: 🧹 Nitpick | 🔵 Trivial

Remove unused import DOM_SEP__CLAIM_A.

DOM_SEP__CLAIM_A is imported but no longer used in this file since signMigrationModeA was moved to mode-a/signature.ts. Only DOM_SEP__CLAIM_B and DOM_SEP__MSK_M_GEN are used here.

🧹 Proposed fix
 import {
-  DOM_SEP__CLAIM_A,
   DOM_SEP__CLAIM_B,
   DOM_SEP__MSK_M_GEN,
 } from "../constants.js";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ts/aztec-state-migration/mode-b/signature.ts` around lines 3 - 7, The file
imports an unused constant DOM_SEP__CLAIM_A; remove DOM_SEP__CLAIM_A from the
import list at the top of signature.ts so only DOM_SEP__CLAIM_B and
DOM_SEP__MSK_M_GEN are imported, keeping the rest of the import statement and
symbols unchanged.
♻️ Duplicate comments (1)
ts/aztec-state-migration/wallet/migration-base-wallet.ts (1)

231-235: ⚠️ Potential issue | 🟠 Major

Avoid global ABI-length hard failure across historical txs.

Line 231 enforces the same abiTypes.length for every tx and throws on mismatch. This still breaks mixed historical flows where txs emitted different note/event counts. Prefer per-tx ABI mapping (or tolerant filtering) instead of aborting the whole retrieval.

Also applies to: 240-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ts/aztec-state-migration/wallet/migration-base-wallet.ts` around lines 231 -
235, The current strict check in migration-base-wallet.ts that throws when
abiTypes.length !== notes.length (and the similar check at 240-244) must be
replaced with tolerant per-transaction handling: instead of aborting, map or
filter notes to ABI entries on a per-tx basis (using txHash to log mismatches)
and proceed with only the matching pairs; update the logic in the function that
compares abiTypes and notes (referencing the abiTypes array, notes array, and
txHash) to either (a) align by index up to min(abiTypes.length, notes.length)
and process those, or (b) use a per-tx ABI mapping to match events to types, and
emit a warning/log via the existing logger when mismatches occur rather than
throwing an Error so historical mixed-format transactions do not halt retrieval.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/publish.yml:
- Around line 54-57: The "Set version" step currently interpolates
inputs.version directly into run, creating a command-injection risk; change the
step to place inputs.version into an environment variable (e.g., env: VERSION:
${{ inputs.version }}), validate that $VERSION matches an allowed pattern (for
example a strict semver regex like ^[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9.-]+)?$)
and fail early if it doesn't, and then call npm version using the safe, quoted
env var (npm version "$VERSION" --no-git-tag-version); keep the step name "Set
version" so it's easy to locate and ensure validation occurs before executing
npm.
- Around line 60-67: The workflow conditional uses dot notation on a hyphenated
input key (if: inputs.dry-run and if: ${{ !inputs.dry-run }}) which parses as a
subtraction; change both conditions to bracket notation (e.g., inputs['dry-run']
and !inputs['dry-run']) so the workflow correctly accesses the "dry-run" input;
update the two occurrences surrounding the npm publish step and the subsequent
Publish step to use bracket access.

In `@e2e-tests/package.json`:
- Around line 1-25: The new workspace package "@aztec-state-migration/e2e-tests"
was added in e2e-tests/package.json but docs/architecture.md wasn't updated;
edit docs/architecture.md to add this e2e-tests component to the component
catalog/topology (including name "@aztec-state-migration/e2e-tests", purpose
(end-to-end tests/state-migration validation), and its placement in the
workspace/deployment topology), ensuring the change satisfies the repo guideline
for files matching **/*.{ts,tsx,json,toml,md}.

In `@e2e-tests/test-utils.ts`:
- Around line 399-401: The check `if (!messageBlock)` incorrectly treats a valid
falsy block value (e.g., 0) as missing; change it to an explicit nullish check
when handling the result of aztecNode.getL1ToL2MessageBlock(messageHash) (for
example use `messageBlock == null` or `messageBlock === null || messageBlock ===
undefined`) before returning undefined, keeping the rest of the logic (including
the subsequent call to aztecNode.getProvenBlockNumber()) unchanged.

In `@ts/aztec-state-migration/key.ts`:
- Around line 1-13: Document the new master migration key derivation in
docs/security.md: add an entry describing deriveMasterMigrationSecretKey (the
function) and the use of sha512ToGrumpkinScalar with the domain separator
DOM_SEP__MSK_M_GEN, state the intended trust assumptions, domain-separation
rationale, attacker/usage model (what this key is for: migration
signing/encryption), and any migration/compatibility notes; ensure the wording
matches the repository's security-doc style and references the exact symbols
deriveMasterMigrationSecretKey and DOM_SEP__MSK_M_GEN so reviewers can correlate
the code change to the documented rationale.

In `@ts/aztec-state-migration/mode-b/proofs.ts`:
- Around line 27-30: The JSDoc for buildNullifierProof is out of date: update
the parameter name from blockNumber to blockReference in the function's comment
block so it matches the actual signature (buildNullifierProof(node: AztecNode,
blockReference: BlockNumber | BlockHash, noteDao: NoteDao)); also adjust any
descriptive text referencing a numeric block to reflect that blockReference may
be a BlockNumber or BlockHash and ensure param name matches the JSDoc `@param` tag
and any examples in the same comment.

In `@ts/aztec-state-migration/proofs.ts`:
- Around line 35-37: Update the thrown Error in the witness lookup failure to
include the lookup key uniqueHash along with noteDao.noteHash so the error
message contains both identifiers; locate the throw in proofs.ts (the block that
currently throws `Could not get note hash membership witness for note
${noteDao.noteHash.toString()}`) and append or interpolate the uniqueHash value
(the variable used for the lookup) into the message to provide both noteHash and
uniqueHash for easier triage.

In `@ts/aztec-state-migration/wallet/entrypoints/browser.ts`:
- Line 10: The import should mark EmbeddedWalletOptions as a type-only import to
match project conventions: split the current import of EmbeddedWalletOptions and
WalletDB into a type import for EmbeddedWalletOptions and a regular import for
WalletDB, i.e. keep WalletDB as a value import and change EmbeddedWalletOptions
to a type import so symbols EmbeddedWalletOptions and WalletDB are imported
appropriately.

In `@ts/aztec-state-migration/wallet/migration-base-wallet.ts`:
- Around line 329-333: Update the stale JSDoc that still refers to "batch" or
"notes" to reflect the new single-note API: change descriptions to singular
language for the note parameter and any mention of processing multiple notes,
and ensure param tags for blockReference, note, and noteMapper and the `@returns`
description describe a single decoded note (storage slot, randomness, nonce,
sibling path). Apply the same singular wording fixes to the other affected JSDoc
blocks (the ones around the comment groups that include lines referencing notes
at the later locations).
- Around line 190-198: The loop that calls this.getPrivateEvents inside "for
(const [txHash, notes] of noteByTxHash)" is performing network requests
serially; change both occurrences (the loop around getPrivateEvents and the
similar loop at the later block) to build an array of promises (e.g., map over
noteByTxHash entries calling getPrivateEvents with eventFilter(txHash) and the
same eventSelector/abiType) and await them with Promise.all (or
Promise.allSettled if per-tx failure isolation is needed), then re-associate
results to their txHash to preserve logic; ensure error handling is adjusted
accordingly so a single failed fetch doesn’t block all other txs.
- Around line 278-281: The code uses allNotes.map(...) solely for side effects
which triggers the lint rule; change the iterator to a side-effect construct
such as allNotes.forEach(...) (or a for...of loop) so the callback's return
value isn't ignored; update the block that references allNotes and noteByTxHash
(the anonymous callback that gets currentNotes via noteByTxHash.get and then
sets noteByTxHash.set) to use forEach/for...of instead of map to satisfy
lint/suspicious/useIterableCallbackReturn.

---

Outside diff comments:
In `@ts/aztec-state-migration/mode-b/signature.ts`:
- Around line 3-7: The file imports an unused constant DOM_SEP__CLAIM_A; remove
DOM_SEP__CLAIM_A from the import list at the top of signature.ts so only
DOM_SEP__CLAIM_B and DOM_SEP__MSK_M_GEN are imported, keeping the rest of the
import statement and symbols unchanged.

---

Duplicate comments:
In `@ts/aztec-state-migration/wallet/migration-base-wallet.ts`:
- Around line 231-235: The current strict check in migration-base-wallet.ts that
throws when abiTypes.length !== notes.length (and the similar check at 240-244)
must be replaced with tolerant per-transaction handling: instead of aborting,
map or filter notes to ABI entries on a per-tx basis (using txHash to log
mismatches) and proceed with only the matching pairs; update the logic in the
function that compares abiTypes and notes (referencing the abiTypes array, notes
array, and txHash) to either (a) align by index up to min(abiTypes.length,
notes.length) and process those, or (b) use a per-tx ABI mapping to match events
to types, and emit a warning/log via the existing logger when mismatches occur
rather than throwing an Error so historical mixed-format transactions do not
halt retrieval.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b87c09 and e8bc44a.

📒 Files selected for processing (38)
  • .github/workflows/publish.yml
  • .gitignore
  • README.md
  • e2e-tests/deploy-types.ts
  • e2e-tests/deploy.ts
  • e2e-tests/migration-key-registry.test.ts
  • e2e-tests/migration-mode-a.test.ts
  • e2e-tests/migration-mode-b.test.ts
  • e2e-tests/migration-public-mode-b.test.ts
  • e2e-tests/package.json
  • e2e-tests/test-utils.ts
  • package.json
  • ts/aztec-state-migration/bridge.ts
  • ts/aztec-state-migration/index.ts
  • ts/aztec-state-migration/key.ts
  • ts/aztec-state-migration/mode-a/index.ts
  • ts/aztec-state-migration/mode-a/proofs.ts
  • ts/aztec-state-migration/mode-a/signature.ts
  • ts/aztec-state-migration/mode-b/index.ts
  • ts/aztec-state-migration/mode-b/proofs.ts
  • ts/aztec-state-migration/mode-b/signature.ts
  • ts/aztec-state-migration/noir-contracts/MigrationArchiveRegistry.lazy.ts
  • ts/aztec-state-migration/noir-contracts/MigrationArchiveRegistry.ts
  • ts/aztec-state-migration/noir-contracts/MigrationKeyRegistry.lazy.ts
  • ts/aztec-state-migration/noir-contracts/MigrationKeyRegistry.ts
  • ts/aztec-state-migration/noir-contracts/index.ts
  • ts/aztec-state-migration/noir-contracts/lazy.ts
  • ts/aztec-state-migration/package.json
  • ts/aztec-state-migration/polling.ts
  • ts/aztec-state-migration/proofs.ts
  • ts/aztec-state-migration/tsconfig.json
  • ts/aztec-state-migration/types.ts
  • ts/aztec-state-migration/wallet/entrypoints/browser.ts
  • ts/aztec-state-migration/wallet/index.ts
  • ts/aztec-state-migration/wallet/migration-account.ts
  • ts/aztec-state-migration/wallet/migration-base-wallet.ts
  • ts/aztec-state-migration/wallet/migration-embedded-wallet.ts
  • tsconfig.json
💤 Files with no reviewable changes (5)
  • ts/aztec-state-migration/polling.ts
  • .gitignore
  • ts/aztec-state-migration/wallet/index.ts
  • ts/aztec-state-migration/bridge.ts
  • ts/aztec-state-migration/types.ts

@JanKuczma JanKuczma changed the title TS SDK: Support mixed data structures in migration events + lil cleanup TS SDK Mar 2, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
README.md (1)

64-72: ⚠️ Potential issue | 🟡 Minor

Duplicate yarn ts:build in Formatting section.

Line 69 includes yarn ts:build under the Formatting section, but this is a compilation command, not a formatting command. It's already documented in the Compilation section (line 60).

Suggested fix
 ## Formatting

 ```sh
 yarn fmt              # Format all code (Noir, Solidity, TypeScript)
 yarn fmt:check        # Check formatting without modifying files (CI use)
-yarn ts:build         # Compile TypeScript
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @README.md around lines 64 - 72, Remove the duplicate compilation command
from the Formatting section: locate the "## Formatting" heading and the list
item containing "yarn ts:build" and delete that line so only formatting-related
commands remain (keep "yarn fmt" and "yarn fmt:check"); compilation commands
such as "yarn ts:build" should remain only in the Compilation section where it's
already documented.


</details>

</blockquote></details>

</blockquote></details>
♻️ Duplicate comments (1)
e2e-tests/test-utils.ts (1)

574-577: ⚠️ Potential issue | 🟡 Minor

Use an explicit nullish check for messageBlock.

getL1ToL2MessageBlock may return 0 for messages included in the genesis block. The current !messageBlock check would incorrectly treat block 0 as absent.

Suggested fix
-      if (!messageBlock) return undefined;
+      if (messageBlock == null) return undefined;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e-tests/test-utils.ts` around lines 574 - 577, The nullity check for
messageBlock incorrectly treats block 0 as absent; change the condition in the
code that calls getL1ToL2MessageBlock (variable messageBlock) to use an explicit
nullish check (e.g., messageBlock === undefined or messageBlock == null) instead
of !messageBlock, then keep the existing logic comparing against
getProvenBlockNumber() (proven) and returning messageBlock or undefined
accordingly; update the check around getL1ToL2MessageBlock / messageBlock /
getProvenBlockNumber to ensure genesis block (0) is handled as a valid value.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@e2e-tests/test-utils.ts`:
- Around line 362-369: L1MigratorAbi and InboxAbi are duplicated in
e2e-tests/test-utils.ts and e2e-tests/deploy.ts; consolidate by moving the ABI
definitions into a single shared export (e.g., export const L1MigratorAbi /
InboxAbi from a common module) and update both test-utils and deploy to import
those symbols instead of redefining them; ensure parseAbi usage and exact string
signatures for L1MigratorAbi and InboxAbi are preserved when relocating.

In `@ts/aztec-state-migration/noir-contracts/MigrationArchiveRegistry.lazy.ts`:
- Around line 23-38: The function getMigrationArchiveRegistryContractArtifact
currently uses value-only caching (cachedArtifact) which allows two concurrent
first callers to both import and parse the JSON; fix this by caching the
in-flight Promise instead: introduce a module-level variable (e.g.,
cachedArtifactPromise or reuse cachedArtifact but typed as
Promise<ContractArtifact> | ContractArtifact | undefined), and in
getMigrationArchiveRegistryContractArtifact if the promise is unset create and
assign a Promise from import(...).then(json => loadContractArtifact(json as
NoirCompiledContract)) and return that promise; optionally, when the promise
resolves store the resolved ContractArtifact into cachedArtifact for fast
synchronous reads in future calls. Ensure you reference the existing symbols
getMigrationArchiveRegistryContractArtifact, cachedArtifact (or new
cachedArtifactPromise), and loadContractArtifact when implementing this change.

In `@ts/aztec-state-migration/noir-contracts/MigrationKeyRegistry.lazy.ts`:
- Around line 115-120: Narrow deployWithOpts so its variadic args only accept
the contract constructor signature: stop using a free generic M over
MigrationKeyRegistryContract["methods"]; instead either constrain M to the
constructor key or remove M and type args as
Parameters<MigrationKeyRegistryContract["methods"]["constructor"]> (and
similarly update the overload at the other occurrence on lines 133-134), keeping
opts the same; update the declaration of deployWithOpts to use that constructor
parameter type to prevent non-constructor method signatures from being passed.

---

Outside diff comments:
In `@README.md`:
- Around line 64-72: Remove the duplicate compilation command from the
Formatting section: locate the "## Formatting" heading and the list item
containing "yarn ts:build" and delete that line so only formatting-related
commands remain (keep "yarn fmt" and "yarn fmt:check"); compilation commands
such as "yarn ts:build" should remain only in the Compilation section where it's
already documented.

---

Duplicate comments:
In `@e2e-tests/test-utils.ts`:
- Around line 574-577: The nullity check for messageBlock incorrectly treats
block 0 as absent; change the condition in the code that calls
getL1ToL2MessageBlock (variable messageBlock) to use an explicit nullish check
(e.g., messageBlock === undefined or messageBlock == null) instead of
!messageBlock, then keep the existing logic comparing against
getProvenBlockNumber() (proven) and returning messageBlock or undefined
accordingly; update the check around getL1ToL2MessageBlock / messageBlock /
getProvenBlockNumber to ensure genesis block (0) is handled as a valid value.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e8bc44a and 311ae58.

📒 Files selected for processing (12)
  • .gitignore
  • README.md
  • e2e-tests/deploy.ts
  • e2e-tests/migration-mode-a.test.ts
  • e2e-tests/migration-mode-b.test.ts
  • e2e-tests/nft-migration-mode-a.test.ts
  • e2e-tests/nft-migration-mode-b.test.ts
  • e2e-tests/test-utils.ts
  • package.json
  • ts/aztec-state-migration/noir-contracts/MigrationArchiveRegistry.lazy.ts
  • ts/aztec-state-migration/noir-contracts/MigrationKeyRegistry.lazy.ts
  • ts/aztec-state-migration/package.json
💤 Files with no reviewable changes (1)
  • .gitignore

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
ts/aztec-state-migration/wallet/migration-base-wallet.ts (1)

190-198: 🧹 Nitpick | 🔵 Trivial

Per-tx event fetches are still serialized; consider parallelizing to reduce latency.

Both loops await PXE calls one tx at a time, which scales poorly with many migration txs.

⚡ Minimal refactor direction
- for (const [txHash, notes] of noteByTxHash) {
-   const events = await ...
-   ...
- }
+ const perTx = await Promise.all(
+   [...noteByTxHash.entries()].map(async ([txHash, notes]) => {
+     const events = await ...
+     ...
+     return ...
+   }),
+ );
+ return perTx.flat();

Also applies to: 230-239

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ts/aztec-state-migration/wallet/migration-base-wallet.ts` around lines 190 -
198, The loop over noteByTxHash is making sequential awaits to
this.getPrivateEvents for each tx; refactor to run fetches in parallel by
mapping noteByTxHash entries to promises and awaiting them with Promise.all (or
Promise.allSettled) so multiple calls to getPrivateEvents (using eventSelector,
abiType and eventFilter(txHash)) execute concurrently; ensure you preserve the
association between txHash and its events when collecting results and handle
errors per-promise if needed.
e2e-tests/test-utils.ts (1)

571-586: ⚠️ Potential issue | 🟡 Minor

Use an explicit nullish check for messageBlock.

Line 583 currently treats 0 as absent. This can incorrectly skip a valid block number.

Suggested fix
-      if (!messageBlock) return undefined;
+      if (messageBlock === undefined || messageBlock === null) return undefined;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e-tests/test-utils.ts` around lines 571 - 586, In waitForL1ToL2Message, the
current truthy check "if (!messageBlock)" treats a valid block number 0 as
absent; change this to an explicit nullish check (e.g. "if (messageBlock ==
null)") when inspecting the result of aztecNode.getL1ToL2MessageBlock so that a
returned 0 is handled as a valid block number before comparing with
aztecNode.getProvenBlockNumber().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/publish.yml:
- Around line 24-29: Add a concurrency guard to the publish job so
manual/parallel runs are serialized: under the jobs.publish block (the job with
name "Build & Publish"), add a concurrency stanza such as concurrency: group:
publish-${{ github.ref }} cancel-in-progress: false so runs for the same ref
wait for the prior publish to finish instead of racing; place it at the same
indentation level as runs-on/steps within the publish job.
- Around line 30-37: Replace the three external action tag refs with immutable
commit SHAs to prevent tag retargeting: locate the uses entries for
actions/checkout@v4, actions/setup-node@v4, and noir-lang/noirup@v0.1.4 in the
publish workflow and update each to the corresponding full commit SHA (e.g.,
actions/checkout@<full-sha>, actions/setup-node@<full-sha>,
noir-lang/noirup@<full-sha>), keeping the same inputs (node-version,
registry-url) intact; verify the SHAs against the upstream repos/tags and commit
the updated workflow.

---

Duplicate comments:
In `@e2e-tests/test-utils.ts`:
- Around line 571-586: In waitForL1ToL2Message, the current truthy check "if
(!messageBlock)" treats a valid block number 0 as absent; change this to an
explicit nullish check (e.g. "if (messageBlock == null)") when inspecting the
result of aztecNode.getL1ToL2MessageBlock so that a returned 0 is handled as a
valid block number before comparing with aztecNode.getProvenBlockNumber().

In `@ts/aztec-state-migration/wallet/migration-base-wallet.ts`:
- Around line 190-198: The loop over noteByTxHash is making sequential awaits to
this.getPrivateEvents for each tx; refactor to run fetches in parallel by
mapping noteByTxHash entries to promises and awaiting them with Promise.all (or
Promise.allSettled) so multiple calls to getPrivateEvents (using eventSelector,
abiType and eventFilter(txHash)) execute concurrently; ensure you preserve the
association between txHash and its events when collecting results and handle
errors per-promise if needed.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 22cab34 and 6eee5cc.

📒 Files selected for processing (6)
  • .github/workflows/publish.yml
  • e2e-tests/deploy.ts
  • e2e-tests/test-utils.ts
  • ts/aztec-state-migration/mode-b/proofs.ts
  • ts/aztec-state-migration/wallet/entrypoints/browser.ts
  • ts/aztec-state-migration/wallet/migration-base-wallet.ts

@JanKuczma JanKuczma changed the title TS SDK Restructure TypeScript SDK as publishable npm package Mar 2, 2026
@JanKuczma JanKuczma enabled auto-merge (squash) March 2, 2026 16:03
@JanKuczma JanKuczma merged commit 77181a0 into main Mar 2, 2026
3 checks passed
@JanKuczma JanKuczma deleted the jk-ts-support-event-mixed-data-structures branch March 2, 2026 16:09
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.

3 participants