Skip to content

feat(example): polish arbitrum-london demo for judge-readiness#22

Merged
mike-diamond merged 5 commits into
mainfrom
feat/buildathon-demo-polish
Jun 2, 2026
Merged

feat(example): polish arbitrum-london demo for judge-readiness#22
mike-diamond merged 5 commits into
mainfrom
feat/buildathon-demo-polish

Conversation

@mike-diamond

Copy link
Copy Markdown
Contributor

Polish pass on the Arbitrum Open House London Buildathon demo (examples/arbitrum-london) to make it judge-ready. Scope is the example only - no packages/* changes. The Pendle flow (Scenario A) is the live demo; Scenario C (RWA on Robinhood) is honestly framed as roadmap.

The headline fix: the demo now actually uses @txkit/themes

The app was rendering entirely from hardcoded hex fallbacks, not the design system. Proven via getComputedStyle: <html> had class="txkit-dark" but the real selector is .tx-dark (+ .tx-root for the base), and globals.css referenced non-existent --txkit-color-* vars. So --tx-color-bg / --tx-color-primary were empty and everything fell back to #0a0a0a / #5b8cff.

Fix (2 files): <html class="tx-root tx-dark"> + import @txkit/themes/base and /dark, and bridge the real --tx-* tokens onto the --color-* names the components already reference. The brand indigo, slate-tinted dark surfaces, IBM Plex Mono, spacing, radii and semantic colors now all come from the design system - which is the point of the demo. Verified live (tokens resolve, mono = IBM Plex Mono).

Other changes

  • EnvelopePreview (hero): prominent action header + human-readable "what happens" line, middle-ellipsis monospace addresses (0x9a7C…8E90), sectioned layout, optional feeSlot.
  • SequencerFeeRow (new, Pendle only): live Arbitrum L1-calldata + L2-compute split via @txkit/arbitrum-adapter previewSequencerFee, fetched with react-query through the wagmi public client. Loading hint; a null preview (RPC down or simulated call reverts) renders nothing rather than blocking the envelope.
  • Landing: leads with the value prop ("Verify before you sign") and an ERC-8265 / PR #1753 credential chip; promotes the working Pendle card, demotes Scenario C to an honest "Roadmap - Phase 2" card.
  • PolicyStatusBadge + error surfaces: semantic --tx-color-success/warning/error tokens instead of hardcoded Tailwind palette.
  • PendleAgentChat: six useState consolidated into one object state; nested ternaries (button label, reply text) replaced with named helpers. Behaviour preserved.
  • Favicon committed; @txkit/arbitrum-adapter added as a workspace dependency.

Verification

  • tsc --noEmit clean.
  • eslint app src/ui clean (the repo-wide eslint errors are all from vendored contracts/lib/** Solidity deps, pre-existing and out of scope).
  • Dev server: landing, /flow-a, /flow-c all render, browser console error-free.
  • EnvelopePreview captured via a temporary mock harness (deleted before commit) since the live hero needs an agent run + a deployed AgentPolicyGate / MockPendleRouter, which is the separate deploy gate.

Decisions baked in (confirmed with Mike)

  • Scenario C: de-emphasized, flow-a is THE demo. Not implemented (that would be a rebuild; buildRwaEnvelope still throws).
  • Refactor depth: full code-rule compliance including the useState consolidation, not just the visual pass.

Known follow-ups (not blockers, not in scope here)

  • The sequencer fee row and the whole Pendle flow only light up once the AgentPolicyGate + MockPendleRouter are deployed (envelope-builder throws on the PENDING router address) - that is the separate deploy runbook.
  • @txkit/themes ships --tx-* tokens but mono/CLAUDE.md still documents the old --txkit-* prefix - a docs drift to fix in the themes package, noted here, not touched.

Not merging - leaving open for review.

- Wire the real @txkit/themes design tokens. The app was rendering entirely
  from hardcoded hex fallbacks: <html> used .txkit-dark (no such selector;
  real one is .tx-dark) and globals.css referenced non-existent --txkit-color-*
  vars. Now <html class="tx-root tx-dark"> + base/dark imports + a --tx-* ->
  --color-* bridge, so the brand indigo, slate dark surfaces, IBM Plex Mono,
  spacing, radii and semantic colors all come from the design system.
- Elevate EnvelopePreview: prominent action header + innerLabel, middle-ellipsis
  monospace addresses, sectioned layout, optional feeSlot.
- Add SequencerFeeRow (Pendle flow only): live L1 calldata + L2 compute split
  via @txkit/arbitrum-adapter previewSequencerFee, fetched with react-query
  through the wagmi public client; loading hint, null degrades to hidden.
- Landing: lead with the value prop + ERC-8265 (PR #1753) credential chip,
  promote the working Pendle flow, demote scenario C to an honest roadmap card.
- PolicyStatusBadge + error surfaces use semantic tokens.
- PendleAgentChat: consolidate six useState into one object state, replace the
  nested ternaries (button label, reply text) with named helpers; behaviour
  preserved.
- Commit the favicon.
@vercel

vercel Bot commented Jun 1, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
txkit-docs Ready Ready Preview, Comment Jun 2, 2026 8:21am
txkit-land Ready Ready Preview, Comment Jun 2, 2026 8:21am
txkit-story Ready Ready Preview, Comment Jun 2, 2026 8:21am

@socket-security

socket-security Bot commented Jun 1, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedeslint-config-next@​15.5.18991006598100
Addedeslint@​9.39.48910010096100
Addedeslint@​10.1.08910010097100
Addedeslint-plugin-react-hooks@​7.0.110010010096100

View full report

…cursor

Adopts the strongest ideas from a Figma Make pass of the same screen, kept on
@txkit/themes tokens and txKit conventions (no lucide / inline SVG, prop-driven,
wired to the real envelope + previewSequencerFee).

- globals.css: restore cursor: pointer on enabled buttons (Tailwind v4 dropped
  the preflight default), so every button across the demo shows the pointer.
- CopyableValue: new component - click-to-copy for addresses and the envelope
  hash with a brief confirmation, plus an optional Arbiscan link (text glyph,
  not an inline SVG).
- EnvelopePreview: live ticking expiry countdown (h/m/s), copyable values via
  CopyableValue with explorer links, and the fee moved to its own section.
- SequencerFeeRow: render an L1 calldata / L2 compute / Total breakdown card
  (Total is the real totalFeeWei from previewSequencerFee) instead of one line.
- PendleAgentChat: pass the Arbiscan base url, add a Reject button beside Sign.

Deliberately skipped from the Figma pass: USD fee equivalents (needs a price
oracle, were mock there) and lucide status icons (txKit uses CSS-mask SVG, and
the badge dot already carries the status).

Verified: tsc clean, eslint clean on the changed files, button cursor computes
to pointer, dev server console error-free.
Code-review follow-ups for PR #22.

- CopyableValue: await navigator.clipboard.writeText and only show the
  'copied' confirmation when it resolves, so a denied clipboard no longer
  shows a false success. The dismiss timeout is tracked in a ref and cleared
  on unmount (and before re-arming) to avoid a setState-after-unmount leak.
- CopyableValue: the explorer link title is now 'View on block explorer'
  (the component is generic; the link can point at Robinhood Chain).
- SequencerFeeRow: derive the chainId from the chain prop instead of a
  hardcoded ARBITRUM_SEPOLIA_CHAIN_ID, so the type contract is honest. The
  wagmi config wires Arbitrum Sepolia, and an unconfigured chain returns an
  undefined client which the queryFn already treats as no preview.
- arbitrum-adapter/sequencer.ts: drop the stray blank line inside the catch.

Verified: example tsc + eslint clean, @txkit/arbitrum-adapter tests 23/23.
…ll3)

The fee row never rendered in the browser. Root cause: wagmi's shared public
client batches reads through Multicall3, and the Arbitrum NodeInterface (0xC8)
is a virtual precompile the node only resolves on a DIRECT eth_call - routed as
a Multicall3 sub-call it returns empty data, so previewSequencerFee always got
null. (Node-side, a plain viem client worked, which masked the issue earlier.)

- SequencerFeeRow: read the precompile through a dedicated plain viem client
  instead of wagmi's usePublicClient. viem does not multicall unless asked, so
  the direct eth_call reaches the precompile. demo: Arbitrum Sepolia only (the
  Pendle flow is the sole caller); this also resolves the earlier nit about the
  hardcoded chain by making the scope explicit in a comment.
- providers + .env.example: NEXT_PUBLIC_ARB_SEPOLIA_RPC_URL configures the
  Arbitrum Sepolia RPC for both the fee client and the wagmi config, falling
  back to the public default. A dedicated RPC (e.g. Alchemy) is recommended:
  the public default is rate-limited for the NodeInterface eth_call.

Verified in-browser against a configured Alchemy RPC: the fee renders
L1 calldata / L2 compute / Total live. The Alchemy url lives in .env.local
(gitignored), never committed. tsc + eslint clean.
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