Skip to content

Add EVM and SVM earn adapters with context providers#17

Open
Timidan wants to merge 71 commits intomasterfrom
feat/phase4-wallet-gate
Open

Add EVM and SVM earn adapters with context providers#17
Timidan wants to merge 71 commits intomasterfrom
feat/phase4-wallet-gate

Conversation

@Timidan
Copy link
Copy Markdown
Owner

@Timidan Timidan commented Apr 24, 2026

Introduce EVM and SVM earn adapters along with necessary context providers to enhance the application's functionality. This update includes routing adjustments and utility functions to support the new adapters.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
web3-toolkit Ready Ready Preview, Comment May 5, 2026 11:58am

Copilot AI review requested due to automatic review settings April 24, 2026 22:14
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3bd31ba9f8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/App.tsx
children,
}) => {
const { activeFamilies } = useWalletManager();
if (activeFamilies.size === 0) return <>{children}</>;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Mount family providers before rendering family routes

FamilyProviderStack renders children without any provider when activeFamilies is empty, but activeFamilies is only populated later in AppInner's useEffect after the first paint. On a fresh session, navigating directly to routes like /evm/builder (or clicking the home quick action) renders components that call wagmi hooks before EvmFamilyProviders is mounted, which triggers hook-context runtime errors and drops users into the error boundary. The family needed by the current pathname should be mounted synchronously on initial render.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Timidan added 9 commits April 24, 2026 23:39
…rver

Branched from feat/phase4-wallet-gate so all Starknet wallet work is
already in place. Engine repo Timidan/starknet-sim is consumed as a
bare gitlink at starknet-sim/ (matching edb/), with no .gitmodules
entry; the gitlink SHA is the contract.

- vercel.json: /api/starknet-sim and /api/starknet-sim/:path* route
  to api/starknet-sim-proxy.ts
- api/starknet-sim-proxy.ts: fork of api/edb-proxy.ts with the
  STARKNET_SIM_BRIDGE_URL / STARKNET_SIM_API_KEY /
  STARKNET_SIM_CORS_ALLOWED_ORIGINS env surface, upstream header
  allowlist, 50 MB body cap, SSE pass-through, no etherscan-key
  injection
- vite.config.ts: injectBridgeCsp now splices both
  VITE_SIMULATOR_BRIDGE_URL and VITE_STARKNET_SIM_BRIDGE_URL origins;
  new /api/starknet-sim dev proxy rewrites to :5790 and injects
  X-API-Key server-side
- src/utils/env.ts: getStarknetSimBridgeUrl() helper mirrors
  getSimulatorBridgeUrl()
- package.json: starknet-sim:build and starknet-sim:server scripts
- .env.example: documents the four new env vars
- starknet-sim/ gitlink at engine commit 1497f0d46cae (initial scaffold)
- src/chains/starknet/simulatorTypes.ts: canonical type mirrors of
  the bridge JSON schemas (SimulateRequest/Response,
  FunctionInvocation recursive tree, FeeEstimate, StateDiff,
  BridgeErrorEnvelope, health/version shapes)
- src/chains/starknet/simulatorClient.ts: StarknetSimulator class
  with health/version/simulate/trace/estimate-fee; AbortController
  timeouts (60s default, 3s for /health), bridge-envelope error
  mapping, self-disable when VITE_STARKNET_SIM_BRIDGE_URL=disabled
- src/components/StarknetSimBridgeStatus.tsx: footer dot polling
  /health every 12s with a 3s timeout, reuses existing
  .edb-status-indicator CSS classes; surfaces git_sha in tooltip
- starknet-sim gitlink bumped to c2e0ae4 (auth middleware, rate
  limiter, route skeleton returning NOT_IMPLEMENTED for §2/§3
  endpoints)

The footer component is not yet mounted in the layout; the active
phase4 wallet work owns the footer container and isn't on origin
yet. Mounting is a one-line drop-in next to EdbBridgeStatus once
phase4 merges.
Engine commits since the previous bump:
- 678d022 feat(§12): Prometheus metrics exporter, API and operations docs
- c2e0ae4 feat(§1,§4): auth middleware, rate limiter, route skeleton

Metrics exporter binds to METRICS_BIND_ADDR (default 127.0.0.1:9090) —
a new env var the deploy runbook (starknet-sim/docs/OPERATIONS.md)
documents; no web-toolkit config change required.
- src/App.tsx: StarknetSimBridgeStatus mounts next to EdbBridgeStatus
  in the footer
- src/chains/capabilities.ts: starknet capability set now includes
  'simulation' and 'tx-replay' so PersistentTools resolves
  /starknet/simulations (capability filter was previously empty)
- src/components/PersistentTools.tsx: lazy-load StarknetSimulationsPage;
  new SimulationsDispatch wrapper routes the 'simulations' tool entry
  by family (starknet → trace view backed by starknet-sim bridge,
  evm → existing SimulationHistoryPage)
- src/components/starknet/StarknetSimulationsPage.tsx: two-tab shell
  (Trace | Synthetic — Sprint 2)
- src/components/starknet/TxTraceView.tsx: felt-validated hash input,
  trace button, summary card (fee/resources/version), invocation tree,
  state diff tabs; surfaces StarknetSimulatorBridgeError codes; shows
  an 'sim disabled' hint when VITE_STARKNET_SIM_BRIDGE_URL=disabled
- src/components/starknet/InvocationTree.tsx: recursive collapsible
  tree with MAX_DEPTH=256 clamp, short-addr and short-selector
  helpers, decodedEntryPoint preferred over raw selector when
  enrichment is present
- src/components/starknet/StateDiffTabs.tsx: storage | nonces |
  classes; counts in tab labels; empty-hint fallbacks
- gitlink bumped to 3ebbc7d (engine): /version now self-reports RPC
  v0.10 and docs point at the Alchemy v0_10 URL shape
- .env.example: documents STARKNET_RPC_URL/_SEPOLIA_URL/_FALLBACK_URL
  with the v0_10 path so operators paste the right shape

The real API key lives only in the droplet env file (and each
developer's local .env, which is gitignored).
Engine at 4803136: RPC client + BlockPin + v0.10 Alchemy integration.

- /health now returns chain_id, spec_version, fork_head (block
  number/hash/timestamp/l1 gas prices), rpc_latency_ms
- /block/:id resolves 'latest', 0x-hex hash, or decimal number;
  rejects 'pending' with 400
- MSRV bumped from 1.85 to 1.86 (reqwest transitives need icu_*
  crates at 1.86); rust-toolchain.toml and CI pinned

No web-toolkit code change beyond the gitlink.
Engine at 91f185e: RpcForkStateReader satisfies blockifier's
StateReader trait (blockifier 0.18.0-rc.1). Verified live against
Alchemy mainnet — reads class hash, storage, nonce; caches
per-session. Sierra→CASM compilation (get_compiled_class) stays
stubbed until §3 executor integration.

MSRV bumped to 1.89 — required by blockifier's transitive
cairo-lang-*/apollo crates. No web-toolkit code change beyond the
gitlink.
Engine at 3c932f4: get_compiled_class now succeeds for legacy
(pre-Sierra) mainnet contracts. Cairo 1 still gates on §3
executor integration.
Engine at 99752f3: /simulate, /trace/:tx_hash, and /estimate-fee
now return real blockifier execution results. Cairo 1 class
loading shipped (Sierra → CASM via cairo-lang-starknet-classes).

Verified live against Alchemy mainnet — synthetic INVOKE v3
against latest block runs end-to-end through the executor
pipeline.
Copilot AI review requested due to automatic review settings April 25, 2026 04:42
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

…s + l2_gas fix

Engine at e496ff5: enrichment layer (revert decoder, resource analyzer,
ABI lookup), golden trace harness over 6 mainnet INVOKE v3 fixtures
(all 6 pass structurally), and a real bug fix in block_context.rs
where L1 gas price was being copied into the L2 GasPriceVector slot
(masked by the synthetic fixture's relaxed bounds; surfaced by real
mainnet txs).
Ports the static docs/sample-sim-ui.html mock into a real React component
tree under src/components/starknet-simulation-results/. Drop-in for
HexKit's existing simulation-results shell.

Components

- StarknetSimulationResults — top-level shell with header (3-step
  status timeline + compact stats row + status pill + INVOKE v3 chip),
  8-tab nav, URL-hash deep-link (#frame=N), keyboard shortcuts
  (b/space/arrows/n/o/j/k for prev/next/step-in/step-out/tree-nav),
  Re-simulate + Explain transaction buttons.
- CallTreeTab — Walnut-style tree with filter input, frame # badges,
  per-frame visual share bars (subtree-size proxy), event badges,
  decoded selectors via the bridge's decodedSelector field (ABI
  cache wins, hardcoded std-lib table is fallback). Right rail:
  Frame detail (decoded calldata + retdata + frame-local events) +
  Cairo source pane (Cairo/Sierra/CASM tier toggle).
- TokenFlowTab — u256 amount decoder (low+high felt packing) +
  per-token decimals (STRK/ETH/USDC/USDT) + ERC721 / ERC1155
  detection. Per-token aggregate chips above the per-event rows.
- EventsTab — dense table with decoded event names (Transfer /
  TransferSingle / Approval / etc.).
- StateDiffTab — canonical envelope from bridge: 4-card summary
  header, storage writes grouped by contract via rowSpan, nonce
  updates, optional class-hash-updates section.
- ResourcesTab — gas waterfall (L1/L1Data/L2 bars), builtins
  distribution chart, per-frame compute heatmap (clickable, jumps
  back to Call tree + selects the frame).
- DevInfoTab — block context / fee estimate / execution resources
  raw key-value tables.

Other

- decoders.ts: KNOWN_SELECTORS / KNOWN_EVENTS / KNOWN_CONTRACTS /
  TOKEN_META static tables + selectorName / eventName /
  contractLabel / shortHex / decodeU256 / formatTokenAmount /
  walkInvocations / countSubtree / subtreeEventCount /
  stripSystemArgs helpers, all reusable across the tabs.
- StarknetSimDemoPage — paste-in /simulate JSON OR Load-sample
  fixture from the github raw URL. Drives StarknetSimulationResults
  with optional onResimulate / onExplainTransaction / onExplainFrame
  hooks for the LLM affordances.
- App.tsx wires /starknet-sim-demo as a top-level lazy route that
  bypasses FamilyShell.
- simulatorTypes.ts: synced StateDiff field names with the bridge's
  canonical envelope (storageDiffs / nonceUpdates / classHashUpdates /
  declaredClasses / summary). Added decodedSelector to FunctionInvocation.
  Removed unused fields (transactionHash, deployedContracts,
  replacedClasses, top-level events / messagesToL1).

Verified end-to-end via playwriter: dev-server route serves, all 86
frames render with bridge-decoded selectors, tabs switch, frame
selection persists to URL hash.
Copilot AI review requested due to automatic review settings April 25, 2026 12:45
The /starknet/simulations route now uses StarknetSimulationResults
instead of the legacy InvocationTree + StateDiffTabs split. Same
input form (paste a tx hash, hit Trace), same /trace bridge call,
but the rendering is the full 8-tab shell with bridge-decoded
selectors, gas waterfall, builtins distribution, frame heatmap,
token flow with u256 decoding, canonical state diff, step debugger,
URL-hash deep linking, and keyboard shortcuts.

Removed the now-unused legacy split components from this view; they
remain on disk for the demo page consumers.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Address P0/P1/P2 findings from /design-taste-frontend audit. Net
result: panels render correctly in both light and dark modes, all
chrome consumes HexKit's CSS-var design tokens, no rolled-our-own
button/badge/card/input/tabs/table primitives.

Color migration

- bg-zinc-* → bg-background / bg-card / bg-muted
- border-zinc-* → border-border
- text-zinc-100/200/300/400 → text-foreground / text-muted-foreground
- accent-zinc-300 → native Checkbox primitive
- emerald-/red-/amber- semantic colors → success/warning/destructive
  variants on Badge

Component swaps

- Custom <button> → <Button variant="outline" loading={…} icon={…}>
- Custom tabs strip → <Tabs>/<TabsList>/<TabsTrigger> (Radix)
- Hand-rolled cards → <Card> (12 sites)
- <table>/<tr>/<td> → <Table>/<TableRow>/<TableCell> (3 tabs)
- <input type=search> → <Input>
- <textarea> → <Textarea>
- <input type=checkbox> → <Checkbox> + <Label>
- Inline error <div> → <Alert variant=destructive>
- Custom long-hex spans → <CopyButton value=…>
- Emoji tab labels → Phosphor icons (TreeStructure, CurrencyCircleDollar,
  RadioButton, Stack, GearSix, Wrench, Code)

UX fixes

- StatusBadge maps SUCCEEDED→success, REVERTED→warning, anything
  else→destructive (was binary success/destructive).
- Trace + Explain pills are now outline (no solid blue fills, per
  feedback_no_blue_button_fills memory rule).
- Selected frame uses bg-accent ring-1 ring-ring (was solid blue).
- onResimulate accepts a Promise + isResimulating prop drives the
  Button loading spinner (was double-click vulnerable).
- details/summary expand bug fixed — tree node click now both
  expands AND selects (was preventDefault-disabled the disclosure).
- #frame=N hashchange listener so back/forward reselects.
- SourcePane shows a real empty state instead of a fake Cairo block
  that looked like real code.
- Empty states across Events/StateDiff/TokenFlow tabs got
  helpful copy + bg-card chrome.
- Stat cards have <Tooltip>s explaining FRI / VM steps.
- Demo page tries /sample-sim.json (public/) before GitHub raw so
  local dev works without internet.
Result Card showed only the absolute UTC string for the simulated
block's timestamp, which is precise but not actionable — users mostly
want to know "is this trace seconds, minutes, or hours old?". Lead
with a coarse "Nm ago" / "Nh ago" / "Nd ago" form and keep the UTC
string in parens for power users who want the exact second; full
string also lives in the title attribute for tooltip-on-hover.

QA: 2-hour-old mainnet trace renders "2h ago (Sat, 25 Apr 2026
15:32:49 GMT)" next to block + starknet-version badges.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Replays of busy mainnet blocks routinely take 30s+; up to now the
only signal that a trace was alive was the spinner on the Trace
button. Add a small "Tracing… Ns elapsed" pill next to the Copy as
cURL action so users know whether to wait or assume a hang.

QA: typed a real tx hash, hit Trace; pill appeared and ticked up
to "Tracing… 2s elapsed" within the first poll, kept ticking until
the bridge response arrived.
Copilot AI review requested due to automatic review settings April 25, 2026 17:52
Iter 37 added a "Tracing… Ns elapsed" pill to the trace flow only.
Lift it into PendingElapsed.tsx with a verb-form prop so the
Speculative simulate ("Simulating") and Estimate fee ("Estimating")
flows surface the same in-flight signal — particularly relevant for
/simulate which can take 30s+ when blockifier replays a busy block,
and for /estimate-fee which now also runs validation by default.

QA: typed an estimate request, hit submit; "Estimating… 0s elapsed"
appeared next to Copy as cURL, ticked up to "Estimating… 1s elapsed"
before the response landed.
Footer used to read "Bridge: starknet-sim-bridge — trace endpoint."
which is fine while you're in the app — the banner above shows the
SHA — but a screenshot shared in chat or attached to a bug loses
that context. Append " @ <short-sha>" to the footer when the bridge
reports git_sha on /health (which it always does), so the result
panel is self-describing in isolation.

QA: real mainnet bridge → footer reads "Bridge: starknet-sim-bridge
@ 468388a — trace endpoint." matching the SHA on the page-level
banner.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Timidan added 2 commits April 25, 2026 20:22
…verage

The result Card was visually noisy compared to Voyager and to our own
EDB simulation results page; trim and reflow to mirror EDB's flow:

Header
- One line: "Starknet simulation" + status pill on the left, Re-simulate
  / Download / Explain icons on the right. Drops the simId / 2-line
  title cluster, the 3-step status timeline, and the 5-stat-card row.

Two-column summary (mirrors EDB's TransactionSummary)
- Left: Hash + Voyager + Starkscan, Network, Block + sn version,
  Time (relative + absolute), Sender (with label).
- Right: Fee (humanized + hex), L1 / L1-data / L2 gas consumed,
  Frames + VM steps.
- Single rounded card; no per-row divider noise; Hash row collapses
  to "speculative · <simId>" on synthetic flows.

Tabs
- Primary strip drops from 8 to 4: Trace / Events / State / L1 messages.
- Token flow / Resources / Dev / Raw move to a smaller right-aligned
  secondary group so they stay one click away without competing for
  attention.

Recent sims sidebar
- Hidden by default; "Show recents" toggle in the page header drives
  it, persisted under hexkit:starknet-sim:showSidebar so the
  preference sticks.

Data coverage wins (no bridge changes, just frontend tables)
- KNOWN_EVENTS adds TransactionExecuted, SponsoredTransaction,
  OutsideExecution, OwnerAdded, OwnerRemoved — covers the Argent /
  AVNU paymaster events we previously rendered as raw hex.
- KNOWN_CONTRACTS adds AVNU AA Forwarder, StarkWare Sequencer,
  Universal Deployer, so call tree, frame detail, events, state diff,
  messages, and token flow all label them consistently.

QA on real mainnet trace 0x5cde…b14:
- Events: 5/5 decoded (was 2/5) — TransactionExecuted x2,
  SponsoredTransaction, Transfer x2.
- Call tree: AVNU AA Forwarder appears as a labelled frame.
- State diff: AVNU AA Forwarder + STRK both labelled (was just STRK).
- Header: ~40% shorter, single summary card replaces stat grid + 3
  status steps + multi-line title block.
… META-TX badge

Frontend wins from the Voyager comparison:

1. Call tree defaults to execute-only — Voyager hides validate /
   fee_transfer behind a toggle and most users only ever look at the
   execute body. Existing toggle wiring kept; just flipping the
   persisted-default. Falls back to the full tree when there's no
   executeInvocation (rare validate-time revert).

2. KNOWN_CLASS_HASHES — Argent, Ready, Braavos, OZ accounts plus a
   couple of token-implementation classes (ERC20Lockable, AVNU AA
   Forwarder Class). frameLabel() resolves these as a third fallback
   between known address and the "Account" selector heuristic, so a
   user account with no entry in KNOWN_CONTRACTS still labels as the
   actual wallet brand ("Ready Account v0.4.0").

3. KNOWN_CONTRACTS — added DAI, wBTC, AVNU Router, JediSwap V1+V2,
   10kSwap, Ekubo Core, MySwap CL.

4. BigInt-keyed indexes on both registries so leading-zero variants
   ("0x036078..." vs "0x36078...") match, since the bridge can return
   either depending on how the felt was serialized upstream.

5. MINT / BURN pill on Token Flow rows when from===0x0 (mint) or
   to===0x0 (burn) — same visual hint Voyager shows on transfer
   visualizations.

6. META-TX badge on the result Card header when any frame in the
   trace dispatches via execute_from_outside_v2 / execute_from_outside
   / execute_sponsored, mirroring Voyager's META-TRANSACTION tag.

QA on a live mainnet trace: __EXECUTE__ section is the only one shown
by default, frame #1 contract reads "Ready Account v0.4.0" pulled
from the class hash 0x36078...45927f, frame detail pane echoes the
same label.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Timidan added 2 commits April 25, 2026 21:29
…arity)

Render the bridge's new decodedFunctionAbi / decodedEventAbi output:

FrameDetailPane
- INPUT block now lists every parameter as `name: cairo::type` paired
  with its consumed slice of the calldata felt array. Primitives
  (felt252, u256, bool) consume the right number of felts; arrays /
  spans use the runtime length-prefix to expand into N indexed items.
- OUTPUT block does the same for retdata.
- Composite struct types (e.g. prop_amm::types::OracleUpdateParams)
  fall through as 1 felt and surface the leftovers under an "extra
  felts (decoder under-consumed)" warning so nothing is hidden.
  Recursive struct expansion needs the bridge to emit the struct's
  field layout — separate follow-up.

EventsTab
- Data column reads the bridge's decoded event field list and renders
  one row per `name: type = value` pair, walking keys[1..] for indexed
  fields then data[] for non-indexed (the standard ERC20/account
  event layout).
- u256 fields render as decimal, primitives as raw hex.
- Falls back to the existing "[N felts]" / token-aware summary when
  the bridge couldn't decode the event (class not loaded).

Bumps the starknet-sim gitlink to 3b078c9 — bridge now emits
decodedFunctionAbi per CallInfo and decodedEventAbi per
SimulationEvent.

QA: live mainnet trace
- Frame #1 __execute__: INPUT shows "calls: Array::<Call> · len=1"
- Frame #2 update_oracle: INPUT shows "pool_id: felt252 = 0x1,
  params: prop_amm::types::OracleUpdateParams" with leftover felts
  under the warning block.
- Events tab Transfer event reads "from: ContractAddress = 0x…,
  to: ContractAddress = 0x…, value: u256 = 50015505375972096".
Previous iter shipped flat decode for primitives + arrays of felts.
Composite types (Array<Call>, structs nesting structs, custom enums)
fell through to the "1 felt + extra-felts warning" fallback because
the frontend didn't have the struct field layouts. Bridge now ships a
top-level `types: { name → {kind, fields|variants} }` registry on
the response (gitlink bumped to d2e9ecc); plumb it through the
TypedParamBlock + DecodedEventFields so every Cairo struct gets
recursively expanded into its fields, including the inner array
items of an Array<StructT>.

- simulatorTypes.ts: SimulateResponse gains `types?` map; new
  AbiTypeDef union (struct | enum).
- consumeForType is now recursive with a depth cap of 8: handles u256,
  bool, Array/Span (recurses into element type), tuples
  (`(felt, u256, …)`), structs (looks up the type registry and
  recurses into each field), enums (renders the discriminator's
  variant name).
- Array elements render with a left border + index label so the tree
  shape is visually obvious for nested structs.
- CallTreeTab + FrameDetailPane + EventsTab take the registry as an
  optional prop; StarknetSimulationResults threads `response.types`
  into both tabs.

QA on a live mainnet trace:
- Frame #1 __execute__ INPUT — calls: Array<Call> len=1 →
  one Call expanded as {to: ContractAddress = 0x20d2…, selector:
  felt252 = 0x231c…, calldata: Span<felt> len=19 with 19 indexed felts}.
- Frame #2 update_oracle INPUT — pool_id: felt252 = 0x1, params:
  OracleUpdateParams expanded as {mid_price: u128, vol_fee_bps: u16,
  bid_side: PiecewiseBookSide {price_0…price_6, total_quantity},
  ask_side: PiecewiseBookSide {…}}. Every nested struct unrolls.
- No "extra felts (decoder under-consumed)" warning anywhere — the
  recursive walker consumes the whole calldata stream cleanly.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Timidan added 5 commits April 25, 2026 22:42
…, IDs, Dev tab tx body)

Frontend half of the bridge gitlink bump (now c21d47c — bridge ships
raw tx body + receipt on /trace responses):

Header
- Re-add the compact 3-step lifecycle pill (Simulated → Accepted on
  L2 → L1 settle) that was dropped in the earlier de-clutter; Voyager
  surfaces this and users want it for at-a-glance state.
- INVOKE v3 tx-type tag back next to the status pill.
- Fee row now reads "0.05 STRK 0xb1b…b00 → StarkWare Sequencer" using
  the existing KNOWN_CONTRACTS resolver against
  blockContext.sequencerAddress (Voyager: "Actual Fee … To: StarkWare
  Sequencer").

TypedParamBlock
- Per-block Hex / Dec / Text segmented control persisted under
  hexkit:starknet-sim:valueFormat. consumeForType is now format-aware:
  - Hex (default): leaf felts render as 0x… raw.
  - Dec: BigInt(felt).toString().
  - Text: ASCII decode when every byte is printable, else falls
    back to hex.
  - u256 / bool / arrays unaffected (already render in their
    natural form).
- Tail "extra felts" block also honors the toggle.

EventsTab
- New ID column rendering Voyager's `<block>_<txPos>_<eventIdx>`
  triple. blockNumber + txPosition threaded from
  StarknetSimulationResults. Cross-references map cleanly to a
  Voyager `/event/<id>` URL.

DevInfoTab
- New "Transaction body" section: hash, type, version, sender, nonce,
  tip, nonce/fee DA mode, all three resource_bounds rows, signature
  felts (multi-line), calldata summary with copy-as-JSON, paymaster
  data, account_deployment_data — every field Voyager's Developer
  Info card shows.
- New "Receipt" section: block number, block hash, finality_status
  (ACCEPTED_ON_L2), execution_status (SUCCEEDED), actual_fee,
  on-chain events count, on-chain messages count.
- Existing Block context / Fee estimate (raw) / Execution resources
  sections kept — they stack below the new ones.

Types
- SimulateResponse extended with optional `txBody` + `txReceipt`
  (verbatim Starknet RPC v0.10 shapes).

QA on live mainnet trace 0xd594…16a7fc:
- Header: SUCCEEDED · INVOKE v3 · Simulated › Accepted on L2 › L1
  settle (off-bridge); Fee row: 0.050015 STRK 0xb1b0d64f324b00 →
  StarkWare Sequencer.
- Hex/Dec toggle: mid_price field flipped from 0x8ec28abdaa996a →
  40183347836262762 across every nested struct.
- Events: ID column reads "9157293_0_0" / "9157293_0_1".
- Dev tab: full body + receipt rendered with copy buttons.
…age Block+Age, class label on frame)

Three more parity wins on top of the earlier set:

EventsTab
- Header gets a Hex/Dec/Text segmented control persisted under
  hexkit:starknet-sim:valueFormat — same key the call-tree toggle
  uses, so flipping it once applies to both surfaces.
- DecodedEventFields renders each non-u256 felt through formatFeltValue
  for the chosen format. u256 fields stay decimal (their natural form).

StateDiffTab
- Storage diff table picks up Block + Age columns (rendered when the
  caller passes blockNumber / blockTimestamp). Voyager shows the same
  on every storage row; useful when many txs land in one batch.
- humanRelativeTs returns "Nm/Nh/Nd ago" — same shape the result-Card
  header uses, just adapted from a Date to an epoch-seconds number.

CallTreeTab
- Selected-frame's classHash row now leads with the class-hash label
  resolved via decoders.classLabel ("Ready Account v0.4.0" before the
  raw hash), matching the "Class: Ready" affordance on Voyager's
  Internal Calls > More Details view.

QA on live trace:
- Events Hex → Dec: hash 0xd594…16a7fc → 3773639095521011387…62812;
  Transfer.from 0x4678…61b5 → 1992221558775053…74607694261.
- Storage diff rows now show "9,157,293 / 1h ago" columns alongside
  Before/After.
- Frame #1 detail pane reads "classHash: Ready Account v0.4.0
  0x36078…45927f".
Was: calldata: [0x1, 0x20d2431b…617fb6, 0x231c178b…5cf8a5, 0x13, …+19]
Now: calldata: (calls: Array<Call>)

When the bridge resolved decodedFunctionAbi for the frame, render the
input list as a Cairo-style signature `(name: Type, …)` instead of a
truncated hex felt array. Carries the same information density Voyager
shows on its Internal Calls table without forcing the user to expand
the FrameDetailPane to see what the parameters mean. Falls back to the
existing felt preview when ABI is unavailable (revert paths,
unverified classes).

QA: Frame #1 row reads "(calls: Array<Call>)"; Frame #2 row reads
"(pool_id: felt252, params: OracleUpdateParams)".
Closer to Voyager parity on the FrameDetailPane and the summary header:

TypedParamBlock — Decoded / Raw view toggle
- Voyager has a per-block Decoded/Raw switch beside Hex/Dec/Text. Add
  it. Decoded (default) is the structured ABI walker. Raw renders a
  flat indexed felt list, useful when the ABI is wrong / missing or
  when you just want to copy a specific felt.
- Both views honor the existing Hex/Dec/Text format toggle, so flat
  Raw output respects the user's preferred base.

Sponsor hint
- When isMetaTx fires (any execute_from_outside_v2 / execute_sponsored
  frame), pull the AVNU AA Forwarder's callerAddress as the
  paymaster's address — that's the convention the Argent / AVNU
  flows use. Surface as "· sponsored by 0x4824…ee16" inline next to
  the Sender row, matching Voyager's "Sponsored by 0x…" affordance.

QA on a paymaster-style trace: the sender / sponsor pair both show
inline; switching Raw vs Decoded flips a 18-line typed struct view
into a 19-row indexed felt list.
Was: 3-step lifecycle showed "Accepted on L2" whenever a tx hash was
set, which misrepresents pre-confirmed traces.

Now: read response.txReceipt.finality_status. Pre-confirmed traces
show "Speculative · Pending L1 settlement"; ACCEPTED_ON_L2 shows
"Accepted on L2 · Pending L1 settlement"; ACCEPTED_ON_L1 lights all
three dots green and reads "Settled on L1" — matching Voyager's
TRANSACTION EXECUTED → Received → Accepted on L2 → SETTLED → Accepted
on L1 chain.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Timidan added 3 commits April 25, 2026 23:29
…diff)

End the manual eyeball-the-DOM loop. Standalone tool that loads our
page and Voyager side-by-side via playwriter, runs a per-tab schema
of locators, and emits a markdown table with every gap classified
✅ / ⚠️ / ❌ / ➕ / 🛑.

Pieces:
- schema.ts — declarative {tab → field → {ours, theirs, normalize, weight}}.
- capture.ts — three phases that each fit in playwriter's 10s -e
  budget: navigate, wait-poll, extract. Each phase is a self-contained
  payload built per (side, tab, txHash).
- diff.ts — pairs fixtures, applies normalize fns, classifies, emits
  report.md with per-tab tables.
- run.sh — orchestrator. Loops tabs, sends payloads to playwriter
  sessions 1 (Voyager) + 3 (ours), waits up to 90s per page for the
  ready signal, runs the diff.
- fixtures/ — JSON snapshots committed so reruns are diffable.

Anchor data-attrs on our DOM so locators don't depend on visible
strings:
- SummaryRow → data-summary-row (slugged label)
- DevRow → data-dev-row
- StatusBadge → data-status
- CallNode tree row → data-frame-row=<walkOrderIndex>

First-run baseline against tx 0xd5949557…16a7fc:
- 19/26 fields match (73%); remaining failures are mostly schema
  selector bugs (slug mismatch on `data-summary-row=l1Gas` vs
  rendered `l1-gas`) — to be tightened in the next iter.

Usage: `tools/voyager-parity/run.sh [tx-hash]` — output goes to
`report.md` next to the script.
Iter on the parity harness now that the scaffold is live:

- Schema: every Voyager-side selector rewritten to use ancestor xpath
  walks (`text=/^Hash$/i >> xpath=ancestor::*[2] >> text=/0x.../`)
  instead of fragile sibling chains. Catches the real values now.
- Schema: add a status normalize that maps Voyager's "TRANSACTION
  EXECUTED" + ours "SUCCEEDED" to the same canonical "succeeded" so
  format-only differences don't false-fail.
- Schema: switch boolean checks (sponsoredBy, feeRecipient, l1TxHash)
  to `exists` matchers — they assert "did the row render" not "what
  text", which is what's actually being compared.
- Capture: per-tab wait probes split by side. Voyager probes by
  visible text. Our side probes by the same data-* anchors the
  extract phase uses (count > 0), eliminating the race where text
  appears via a tooltip / breadcrumb / localStorage hint before the
  actual data-mounted DOM lands.
- Capture: per-locator 1.5s timeout in extract — fits 15-field
  overview comfortably under playwriter's 10s -e cap.

Baseline result against tx 0xd594…16a7fc: 15/26 (58%) match.
Remaining ⚠️/❌ rows are real gaps:
- overview.l1TxHash / signatureCount / l1Gas (3) are Dev-tab data
  Voyager surfaces on the Overview header — we hide them behind the
  Dev secondary tab.
- internalCalls.callCount / hasExecuteFn — race where the inner
  result tab navigation reloads the page mid-trace; needs a settle.
- storage.writeCount off-by-one (11 vs 12) — likely table header row
  counted; minor selector fix.

Format-only diffs (sender truncation, fee precision) intentionally
left as ⚠️ rather than masked; they're benign but visible.
…wer recents

Match the EDB simulation page layout you asked for:

- Page wrapper drops max-w-7xl in favor of `w-full` with
  `clamp(1rem,3vw,2.5rem)` padding so the result card actually
  reaches the viewport edges. On a 1600px viewport the result Card
  goes from 1194px → 1470px wide.
- Each result section gets its own bordered container card. The
  sticky header (status pill + actions + lifecycle) was already its
  own header element; wrap the tabs panel in a `border border-border
  rounded-md bg-card` so the hierarchy is the same as EDB's
  Summary / Contracts / Events / State stack.
- Sticky page header pinned to the top of the result Card with a
  flat border-bottom, mirroring `.sim-results-header`.
- Recent sims sidebar moves out of the grid template into a fixed
  top-right drawer (`fixed top-4 right-4 z-30 w-[260px]`) so it
  never steals horizontal real estate from the result column,
  whether the user toggles it on or off.

Note: the "events show 1 instead of 5" / "trace shows 1 frame" bugs
you saw earlier were stale React state from prior trace responses
(bridge can return different counts as fork-head moves past the tx's
block). After a hard reload both render the correct 5 events / 4
frames. The non-determinism is a separate bridge concern; this
commit doesn't address it.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Timidan added 2 commits May 5, 2026 11:30
- Updated ExecutionStackTrace.css to include fallback design tokens for I/O sections, ensuring consistent styling across components.
- Enhanced getBridgeHeaders function in env.ts to allow for optional method parameter, adjusting Content-Type header based on request type.
- Updated submodule reference for starknet-sim.
- Removed obsolete capture and diff scripts from voyager-parity, streamlining the project structure.
- Deleted outdated fixture files for events, internalCalls, overview, and storage from voyager-parity.
- Cleaned up run.sh and schema.ts scripts in voyager-parity, removing unnecessary complexity and improving maintainability.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

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.

2 participants