Skip to content

feat: real-time escrow status timeline with optimistic updates (#26) - #46

Merged
meshackyaro merged 1 commit into
workman-labs:devfrom
jayteemoney:feat/escrow-status-timeline
Aug 24, 2026
Merged

feat: real-time escrow status timeline with optimistic updates (#26)#46
meshackyaro merged 1 commit into
workman-labs:devfrom
jayteemoney:feat/escrow-status-timeline

Conversation

@jayteemoney

Copy link
Copy Markdown
Contributor

Summary

Implements #26 — a real-time escrow status timeline with optimistic updates. The new route /escrow/[bookingRef]/timeline renders the escrow's on-chain lifecycle as a live, chronological timeline. User actions apply optimistically and either confirm into the history (with a tx hash + timestamp) or roll back gracefully on failure; a visibility-aware background poll keeps the timeline in sync with the authoritative status.

The lifecycle mirrors the Soroban escrow contract's Status in guildworkman-core:

funded ──release──▶ completed (terminal)
       ──cancel───▶ cancelled (terminal)
       ──dispute──▶ disputed ──resolve──▶ resolved (terminal)

What's included

  • src/lib/escrowTimeline.ts — pure lifecycle model: statuses, legal actions (actionsFor), and a single pure timelineReducer (SUBMIT / CONFIRMED / FAILED / SYNC / DISMISS_ERROR) over an append-only event log, so optimistic-apply-then-rollback is a modeled transition, not ad-hoc useState. Plus buildTimelineNodes.
  • src/lib/escrowChain.ts — an isolated simulated on-chain source (latency, an occasional failed submission, an in-memory ledger the poll reads). Same rationale as the existing fundEscrow() stub: the Soroban escrow contract has the methods, but no backend REST/RPC endpoint exposes them to the web app yet. Swap these two functions for real calls and nothing else changes.
  • src/components/escrow/useEscrowTimeline.ts — wires the reducer to the chain: optimistic submit + confirm/rollback, and visibility-aware polling (pauses on hidden tab, refreshes on return).
  • EscrowTimeline.tsx / EscrowTimelinePanel.tsx — accessible vertical timeline (aria-live optimistic node, role="alert" rollback, live-sync indicator); action buttons are derived from the legal transitions and disabled while a submission is in flight.
  • Route /escrow/[bookingRef]/timeline, plus a "Track escrow status" link from the funding wizard's funded state.
  • docs/escrow-status-timeline.md + a README "Known limitations" entry documenting the architecture and the stub follow-up.

Architecture notes

  • Event log, not a mutable status field — the timeline is a history, so history: ConfirmedEntry[] is the source of truth and the optimistic action is a single pending node appended after it. Rollback is "drop the pending node"; the confirmed history is untouched by construction.
  • Stale-safe reconciliationSYNC commits an in-flight action whose target it observes, adopts a legal external change (dropping any now-impossible optimistic node and noting the snap-back), and ignores states it can't reconcile; stale confirmations/failures are dropped by submission-id matching.
  • No new dependencies — React (incl. useSyncExternalStore for hydration-safe timestamps), react-icons, the existing ui/* primitives and Tailwind tokens (light/dark both work).

Tasks / acceptance criteria

  • Reviewed Next.js App Router structure; matched existing escrow/wizard conventions
  • UI components implemented with responsive Tailwind + design tokens
  • npm dependency caching in CI already present (actions/setup-node cache: npm)
  • npm run lint — clean (no new warnings), npm run typecheck — no errors
  • npm run build — production build succeeds; /escrow/[bookingRef]/timeline emitted
  • Optimistic update + graceful rollback + real-time sync verified in-browser; 0 console errors / no hydration warnings

Verification

  • npm run typecheck → no errors
  • npm run lint → 0 errors (pre-existing warnings only, none in new code)
  • npm test110 passed (incl. 22 new reducer/metadata tests)
  • npm run build → success
  • Manually walked funded → disputed → resolved in the running app: optimistic nodes, tx-hash confirmation, action narrowing, and terminal state all correct.

Closes #26

🤖 Generated with Claude Code

…an-labs#26)

Render a live escrow lifecycle timeline that reflects on-chain state
changes, applies user actions optimistically, and rolls back gracefully
on failure.

- escrowTimeline.ts: pure lifecycle model (funded -> completed | cancelled
  | disputed -> resolved, mirroring the Soroban escrow contract's Status)
  as an append-only event log with a single pure reducer handling submit /
  confirm / fail / sync, plus buildTimelineNodes.
- escrowChain.ts: isolated simulated on-chain source (latency, occasional
  failure, in-memory ledger) so the flow is exercised today; swap its two
  functions for a real endpoint when the backend Soroban integration lands.
- useEscrowTimeline: wires the reducer to the chain with optimistic submit
  and visibility-aware polling for real-time reconciliation.
- EscrowTimeline / EscrowTimelinePanel: accessible vertical timeline, action
  buttons derived from the legal transitions, live-sync indicator, and
  inline rollback error with retry.
- Route /escrow/[bookingRef]/timeline; "Track escrow status" link from the
  funding wizard's funded state.
- 22 reducer/metadata unit tests (110 total pass); lint, typecheck and
  production build clean.

Closes workman-labs#26
@vercel

vercel Bot commented Aug 24, 2026

Copy link
Copy Markdown

@jayteemoney is attempting to deploy a commit to the Meshack Yaro's projects Team on Vercel.

A member of the Team first needs to authorize it.

@meshackyaro meshackyaro left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Excellent work on this PR! This is a thoughtfully architected implementation that demonstrates strong full-stack thinking.

Standout observations:

  • Event-sourced architecture — modeling the timeline as an append-only event log is elegant and directly mirrors the on-chain escrow contract lifecycle. Optimistic updates and rollback become natural state transitions rather than ad-hoc mutations.

  • Stale-safe reconciliation — the SYNC action thoughtfully handles real-world timing issues (visibility changes, network delays). Dropping stale confirmations by submission-id and reconciling external changes without corrupting optimistic nodes shows maturity in thinking about distributed systems.

  • Zero new dependencies** — a polished, accessible UI using only React, existing primitives, and Tailwind. The visibility-aware polling is a nice touch for both UX and backend load.

  • Test coverage — 22 new tests for the reducer and metadata are well-earned; verification walkthrough from funded → disputed → resolved shows care for actual usage.

  • Documentation — docs/escrow-status-timeline.md + clear inline comments make the design intent obvious, lowering the maintenance burden for the team.

The transition from stubs to real Soroban calls is well-isolated; the follow-up swap will be straightforward. Clean build, no hydration warnings, and the PR description is unusually thorough.

Really solid contribution. Well done!

@vercel

vercel Bot commented Aug 24, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
guildworkman-web Ready Ready Preview Aug 24, 2026 5:12am

@meshackyaro
meshackyaro merged commit 7da9c9a into workman-labs:dev Aug 24, 2026
3 checks passed
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.

Real-Time Escrow Status Timeline with Optimistic Updates

2 participants