Skip to content

feat(bootstrap): typed constructor inputs in deploy form#530

Merged
kariy merged 7 commits intomainfrom
refactor/formatted-constructor
Apr 10, 2026
Merged

feat(bootstrap): typed constructor inputs in deploy form#530
kariy merged 7 commits intomainfrom
refactor/formatted-constructor

Conversation

@kariy
Copy link
Copy Markdown
Member

@kariy kariy commented Apr 9, 2026

The bootstrap TUI currently requires users to enter constructor calldata as raw comma-separated felt values. This is error-prone and requires manually looking up the ABI to know the expected argument order, types, and encoding (e.g. u256 must be split into low/high felts, ByteArray must be chunked into 31-byte words).

This PR adds an ABI parsing layer (crates/bootstrap/src/abi.rs) that extracts the constructor signature from a Sierra class and resolves each input into a typed AST. The deploy form in the TUI now introspects the selected class's ABI and presents one labeled input field per constructor argument, showing the argument name and a type hint. Values are automatically encoded into the correct felt sequence on save — users type a plain number for u256, a string for ByteArray, JSON for arrays/structs, and hex literals for felts.

u256 and ByteArray are special-cased to resolve as primitives rather than their underlying struct representations, so the user enters a single value instead of filling in internal fields like {low, high} or {data, pending_word, pending_word_len}.

When a class has no introspectable ABI (legacy classes, missing or invalid ABI), the form falls back to the original raw calldata input. Editing an existing deploy entry that already has raw calldata preserves it in raw mode to avoid lossy reverse-encoding.

The expensive class_options() call (ABI parsing + embedded class decompression) is deferred to class-cycling and save only — it no longer runs per-keystroke, keeping paste and typing responsive.

Test plan

  • 18 unit tests in abi.rs covering type resolution, calldata encoding (u256 split, ByteArray chunking, struct flattening, arrays, options, booleans), edge cases (Span-as-array, nested structs, u256/ByteArray struct-in-ABI resolution)
  • 8 unit tests in tui.rs covering typed/raw mode selection, form build encoding, class sync with value carry-over, focus navigation, and error reporting

🤖 Generated with Claude Code

kariy and others added 6 commits April 9, 2026 15:37
Port `crates/explorer/ui/src/shared/utils/abi.ts` to Rust as
`katana_bootstrap::abi`. Provides `parse_abi` (constructor + read/write
function lists with resolved `TypeNode` inputs) and `to_calldata`
(encode a `serde_json::Value` against a `TypeNode` into felts), so the
bootstrap crate can later accept typed constructor inputs instead of
raw felt arrays.

JSON Schema generation, `sortedAbi`, and the form-binding helpers from
the TS source are intentionally not ported — no Rust caller needs them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the single raw-calldata text field in the "Add contract" modal
with per-argument inputs derived from the selected class's constructor
ABI. Each field shows the argument name, a dimmed type hint (e.g.
`ContractAddress`, `u256`, `Array<felt252>`), and a text editor. Values
are encoded via `abi::to_calldata` on save, so the executor and manifest
format are unchanged.

The modal is now split into two bordered sections — "Contract" (class
picker, label, salt, unique) and "Constructor" (typed args or raw
fallback) — making the constructor block visually distinct.

Key details:
- u256 is special-cased in resolve_type to stay Primitive (user types a
  single number, split_u256 handles the rest) instead of requiring a
  JSON struct literal.
- class_options() (ABI parse + embedded class decompression) is deferred
  to class-cycling and Enter/build only — no longer called per-keystroke,
  which fixes paste lag.
- Editing an existing entry with raw calldata stays in raw mode to avoid
  lossy reverse-encoding; empty calldata adopts typed mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Treat `core::byte_array::ByteArray` the same way as u256 — resolve it
as a Primitive in the type AST so the user types a plain string instead
of filling in the raw struct fields (data, pending_word,
pending_word_len).

The encoder splits the string into 31-byte big-endian felt chunks
following Cairo's ByteArray Serde layout:
  [num_full_chunks, ...chunks, pending_word, pending_word_len]

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…itives

ContractAddress, ClassHash, EthAddress, and StorageAddress are single-
felt wrapper structs in the Sierra ABI. Without special-casing, the
struct branch tries to JSON-parse a bare hex value as an object and
fails. Treat them as transparent primitives so the user enters one
hex/decimal value that encodes directly as a felt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The edit form was resetting all constructor inputs to empty because
from_existing always created fresh TextInputs. Add from_calldata — the
inverse of to_calldata — to decode existing raw felts back into display
strings and pre-fill the typed inputs.

Supports round-tripping single-felt primitives, u256, ByteArray, bools,
structs, arrays, and options. Falls back gracefully (empty field) when
decoding isn't possible.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Label completed rows with `class hash:` and `address:` so the results
are immediately readable. Align the labels so hex values line up across
declare and deploy rows, and use cyan instead of dark gray so they're
actually visible.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Benchmark

Details
Benchmark suite Current: cc45d37 Previous: caae2a8 Ratio
CompiledClass(fixture)/compress 2712365 ns/iter (± 7843) 2737238 ns/iter (± 48212) 0.99
CompiledClass(fixture)/decompress 2874446 ns/iter (± 15939) 2894584 ns/iter (± 14002) 0.99
ExecutionCheckpoint/compress 32 ns/iter (± 8) 35 ns/iter (± 8) 0.91
ExecutionCheckpoint/decompress 25 ns/iter (± 3) 25 ns/iter (± 2) 1
PruningCheckpoint/compress 32 ns/iter (± 8) 34 ns/iter (± 8) 0.94
PruningCheckpoint/decompress 25 ns/iter (± 7) 25 ns/iter (± 3) 1
VersionedHeader/compress 645 ns/iter (± 9) 642 ns/iter (± 8) 1.00
VersionedHeader/decompress 813 ns/iter (± 17) 814 ns/iter (± 21) 1.00
StoredBlockBodyIndices/compress 77 ns/iter (± 6) 76 ns/iter (± 7) 1.01
StoredBlockBodyIndices/decompress 36 ns/iter (± 8) 36 ns/iter (± 7) 1
StorageEntry/compress 162 ns/iter (± 2) 148 ns/iter (± 3) 1.09
StorageEntry/decompress 141 ns/iter (± 2) 139 ns/iter (± 3) 1.01
ContractNonceChange/compress 161 ns/iter (± 2) 148 ns/iter (± 3) 1.09
ContractNonceChange/decompress 233 ns/iter (± 3) 236 ns/iter (± 3) 0.99
ContractClassChange/compress 224 ns/iter (± 3) 200 ns/iter (± 2) 1.12
ContractClassChange/decompress 249 ns/iter (± 3) 251 ns/iter (± 3) 0.99
ContractStorageEntry/compress 158 ns/iter (± 4) 161 ns/iter (± 4) 0.98
ContractStorageEntry/decompress 309 ns/iter (± 3) 307 ns/iter (± 8) 1.01
GenericContractInfo/compress 136 ns/iter (± 6) 132 ns/iter (± 3) 1.03
GenericContractInfo/decompress 102 ns/iter (± 3) 102 ns/iter (± 4) 1
Felt/compress 82 ns/iter (± 6) 82 ns/iter (± 5) 1
Felt/decompress 55 ns/iter (± 5) 57 ns/iter (± 5) 0.96
BlockHash/compress 81 ns/iter (± 5) 82 ns/iter (± 6) 0.99
BlockHash/decompress 55 ns/iter (± 7) 56 ns/iter (± 4) 0.98
TxHash/compress 81 ns/iter (± 4) 82 ns/iter (± 5) 0.99
TxHash/decompress 54 ns/iter (± 7) 56 ns/iter (± 5) 0.96
ClassHash/compress 81 ns/iter (± 6) 82 ns/iter (± 5) 0.99
ClassHash/decompress 55 ns/iter (± 8) 56 ns/iter (± 5) 0.98
CompiledClassHash/compress 81 ns/iter (± 5) 82 ns/iter (± 6) 0.99
CompiledClassHash/decompress 54 ns/iter (± 1) 56 ns/iter (± 5) 0.96
BlockNumber/compress 47 ns/iter (± 2) 47 ns/iter (± 3) 1
BlockNumber/decompress 25 ns/iter (± 1) 25 ns/iter (± 0) 1
TxNumber/compress 47 ns/iter (± 3) 47 ns/iter (± 5) 1
TxNumber/decompress 26 ns/iter (± 0) 26 ns/iter (± 0) 1
FinalityStatus/compress 1 ns/iter (± 0) 1 ns/iter (± 0) 1
FinalityStatus/decompress 12 ns/iter (± 1) 12 ns/iter (± 0) 1
TypedTransactionExecutionInfo/compress 16232 ns/iter (± 74) 18106 ns/iter (± 539) 0.90
TypedTransactionExecutionInfo/decompress 3587 ns/iter (± 203) 3696 ns/iter (± 121) 0.97
VersionedContractClass/compress 375 ns/iter (± 67) 379 ns/iter (± 11) 0.99
VersionedContractClass/decompress 778 ns/iter (± 21) 783 ns/iter (± 15) 0.99
MigratedCompiledClassHash/compress 146 ns/iter (± 6) 160 ns/iter (± 5) 0.91
MigratedCompiledClassHash/decompress 146 ns/iter (± 6) 139 ns/iter (± 4) 1.05
ContractInfoChangeList/compress 1683 ns/iter (± 40) 1611 ns/iter (± 45) 1.04
ContractInfoChangeList/decompress 2217 ns/iter (± 376) 2246 ns/iter (± 387) 0.99
BlockChangeList/compress 661 ns/iter (± 22) 696 ns/iter (± 57) 0.95
BlockChangeList/decompress 896 ns/iter (± 151) 913 ns/iter (± 162) 0.98
ReceiptEnvelope/compress 30469 ns/iter (± 830) 32091 ns/iter (± 1820) 0.95
ReceiptEnvelope/decompress 6002 ns/iter (± 213) 6186 ns/iter (± 304) 0.97
TrieDatabaseValue/compress 169 ns/iter (± 3) 172 ns/iter (± 30) 0.98
TrieDatabaseValue/decompress 215 ns/iter (± 1) 230 ns/iter (± 1) 0.93
TrieHistoryEntry/compress 288 ns/iter (± 1) 290 ns/iter (± 1) 0.99
TrieHistoryEntry/decompress 260 ns/iter (± 9) 269 ns/iter (± 9) 0.97

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 10, 2026

Runner: AMD EPYC 7763 64-Core Processor (4 cores) · 15Gi RAM

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 10, 2026

Codecov Report

❌ Patch coverage is 73.23556% with 292 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.45%. Comparing base (9bde0ae) to head (cc45d37).
⚠️ Report is 364 commits behind head on main.

Files with missing lines Patch % Lines
crates/bootstrap/src/tui.rs 53.48% 187 Missing ⚠️
crates/bootstrap/src/abi.rs 84.76% 105 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #530      +/-   ##
==========================================
- Coverage   73.32%   66.45%   -6.88%     
==========================================
  Files         209      308      +99     
  Lines       23132    41842   +18710     
==========================================
+ Hits        16961    27805   +10844     
- Misses       6171    14037    +7866     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@kariy kariy merged commit 3e40686 into main Apr 10, 2026
14 of 17 checks passed
@kariy kariy deleted the refactor/formatted-constructor branch April 10, 2026 20:46
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.

1 participant