feat(sdk): load TestJam state from JIP-4 genesis.json - #133
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThis PR implements genesis-driven SDK state loading by introducing a new ChangesSDK State Loading from Genesis
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Wraps typeberry's state_merkleization.loadState to materialise a SerializedState<StateEntries> from a parsed JIP-4 chain spec. This is the inverse of generateGenesis and gives the SDK an explicit, public-facing "load state" API to complement the existing "generate / save" pair. Refs #104 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/jammin-sdk/simulator.test.ts`:
- Around line 176-180: The code uses String.prototype.substring(2) in the
genesis payload construction which violates the Biome noSubstr rule; update all
uses to String.prototype.slice(2) instead. Specifically, replace
genesis.genesisHeader.toString().substring(2) with
genesis.genesisHeader.toString().slice(2), and in the genesis_state mapping
replace key.toString().substring(2) and value.toString().substring(2) with
key.toString().slice(2) and value.toString().slice(2) respectively so linting
passes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: df57859c-ccfd-4d7a-98a9-907e092df167
📒 Files selected for processing (4)
packages/jammin-sdk/simulator.test.tspackages/jammin-sdk/simulator.tspackages/jammin-sdk/utils/genesis-state-generator.test.tspackages/jammin-sdk/utils/genesis-state-generator.ts
TestJam now holds SerializedState<StateEntries> at runtime — the same shape typeberry consumes when it loads genesis.json at deploy-time. The factories build state via generateGenesis + loadStateFromGenesis instead of constructing an InMemoryState directly, so any drift between the SDK's hand-rolled state construction and typeberry's deserialiser is caught by tests rather than only surfacing at deploy time. Refs #104 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New static factory loads SerializedState from a JIP-4 genesis.json file on disk. Default path is ./dist/genesis.json so it 'just works' after a jammin deploy. Missing files throw with a clear hint to run deploy first; malformed JSON / schema errors propagate unmodified from the JSON parser and typeberry's parseFromJson. Closes #104 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sanity check that accumulate() runs against state loaded from a file, exercising the SerializedState branch end-to-end through the new fromGenesis factory. Refs #104 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
TypeScript's strict generic inference for parseFromJson<T> couldn't narrow T from JipChainSpec.fromJson alone (FromJsonWithParser<unknown, JipChainSpec> is one of several union members of FromJson<T>, so inference picks unknown). Pin T explicitly. Refs #104 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
loadStateFromGenesis(genesis)SDK primitive that materialises aSerializedState<StateEntries>from a parsed JIP-4JipChainSpec— the inverse ofgenerateGenesis, and a thin wrapper over typeberry'sstate_merkleization.loadState.TestJam.create()andTestJam.empty()through the new primitive.TestJam.statenow holdsSerializedState<StateEntries>at runtime — the same state shape typeberry consumes when it loadsgenesis.jsonat deploy time, instead of the hand-rolledInMemoryStatethat mirrored JAM service-account semantics ingenerateState. Any drift between SDK construction and typeberry's deserialiser now surfaces in tests, not atjammin deploy && jammin start.TestJam.fromGenesis(path?: string)reads a JIP-4 file from disk, defaults to./dist/genesis.jsonso it "just works" after ajammin deploy. Missing files throw with a clear hint to runjammin deployfirst; malformed JSON / schema errors propagate unmodified fromJSON.parse/parseFromJson.Closes #104.
Behaviour change to flag
TestJam.statepreviously heldInMemoryState; it now holdsSerializedState<StateEntries>for instances built viacreate()andempty()(and the newfromGenesis()). The declared type union is unchanged.accumulate()already branched on both shapes, so no consumer changes are required unless code was narrowingjam.state instanceof InMemoryStatedirectly.Spec & plan
docs/superpowers/specs/2026-05-17-load-sdk-state-from-genesis-design.md(gitignored — workflow artefact only)docs/superpowers/plans/2026-05-17-load-sdk-state-from-genesis.md(gitignored — workflow artefact only)Test plan
bun test packages/jammin-sdk— 163 SDK tests pass (4 new round-trip tests forloadStateFromGenesis; 1 state-shape test forTestJam.empty(); 3 new tests forTestJam.fromGenesis()covering happy path, missing-file error, and anaccumulate()regression).bun test— full suite (SDK + CLI), 193 pass / 0 fail / 1 skip across 14 files.bun run build— clean build, no TS errors.bun run qa— Biome clean.loadStateFromGenesis,TestJam.fromGenesis,TestJam.empty,TestJam.createall reachable throughpackages/jammin-sdk/dist/index.js.Out of scope
jammin deployflow.jammin startor the Docker-based local network.generateState/generateGenesis— they remain the wayjammin deployproduces the file in the first place.genesis.jsonbeyond whatJipChainSpec.fromJsonalready does.🤖 Generated with Claude Code