Skip to content

fix(web): rollback optimistic feed state on failed transaction - #1414

Open
Olajcodes wants to merge 1 commit into
Epta-Node:mainfrom
Olajcodes:fix/issue-1191-feed-optimistic-rollback
Open

fix(web): rollback optimistic feed state on failed transaction#1414
Olajcodes wants to merge 1 commit into
Epta-Node:mainfrom
Olajcodes:fix/issue-1191-feed-optimistic-rollback

Conversation

@Olajcodes

Copy link
Copy Markdown

Summary

When the feed applies an optimistic like/follow/tip mutation, the UI updates immediately for an instant feel. However, if the underlying on-chain transaction reports failed, the optimistic state was never reverted — the feed kept showing a "liked" heart, a "Following" label, or a bumped tip total that was never persisted, and a later unrelated refetch would snap the UI back to server truth, causing a visible flash/unsync.

This PR adds snapshot/rollback support to optimisticStore.ts and wires Feed.tsx to clear its transient "pending" styling when a rollback happens, so the UI always reconciles back to the pre-mutation state on failure.

Type of Change

  • Bug fix
  • New feature
  • Contract change (logic, storage, or API)
  • Documentation update
  • Refactor / chore

Changes

apps/web/src/lib/optimisticStore.ts

  • Added snapshot capture for like, follow, and tip state before each optimistic mutation:
    • snapshotLikeState(key), snapshotFollowState(key), snapshotTipState(key)
  • Added the rollback path that restores the pre-mutation snapshot for the exact post/user affected, clears the snapshot, notifies subscribed React components (so they re-render with the restored state), and emits a rolled-back event:
    • rollbackLikeState, rollbackFollowState, rollbackTipState
  • Added a RolledBackEvent type { kind: "follow" | "like" | "tip"; key: string } and an onRolledBack(listener) subscription (returns an unsubscribe function) so components can clear transient "pending" styling.
  • Snapshots are deep clones (JSON-serialization based) so they never share references with live state.
  • Added clearLikeState / clearTipState counterparts for symmetry and test cleanup.

apps/web/src/components/Feed.tsx

  • Tracks per-post "pending" state (pendingLikes) while an optimistic write is in flight, showing a transient Liking... label and pulse styling.
  • Subscribes to OptimisticStore.onRolledBack and clears the pending styling for the affected post when a like/follow write is rolled back after a failed transaction.

apps/web/src/lib/__tests__/optimisticStore.test.ts (new)

  • Success path — committed optimistic state is retained (no rollback).
  • Failure path — a failed like/follow/tip restores the pre-mutation snapshot and emits a rolled-back event.
  • No-prior-state — when there was no optimistic entry before the write, the rollback drops the entry so the UI falls back to server truth.
  • Partial rollback ordering — rolling back one post/user does not disturb unrelated snapshots, and sequenced rollbacks restore their own state independently.
  • Deep-clone independence — mutating live state after snapshotting cannot corrupt the stored snapshot.
  • onRolledBack unsubscribe stops delivering events.

Testing Done

  • New tests added for changed behaviour: 9 unit tests in apps/web/src/lib/__tests__/optimisticStore.test.ts — all passing.
  • tsc --noEmit from apps/web — the only reported errors are pre-existing ones in packages/sdk (generated client: scvU64/scvSymbol/bigint typing), which are out of scope of this issue; no errors in the files changed here.
  • cargo test passes — N/A (frontend-only change)
  • Manually verified on Testnet (if applicable) — not possible in this environment
  • TypeScript SDK tests passed (if applicable) — N/A

Checklist

  • Changes are focused — one concern per PR (optimistic rollback)
  • If a contract function was added or changed, the README API table is updated — N/A (frontend only)
  • No unresolved merge conflicts
  • No secrets or private keys committed

Related Issue

Closes #1191

Capture a deep snapshot of like/follow/tip state before each optimistic
mutation in optimizerStore and restore it when the on-chain transaction
reports failed, emitting a rolled-back event so the Feed can clear its
transient pending styling. Add unit tests covering success, failure, and
partial rollback ordering.
@drips-wave

drips-wave Bot commented Aug 29, 2026

Copy link
Copy Markdown

@Olajcodes Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@vercel

vercel Bot commented Aug 29, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the Jaja's projects Team on Vercel.

A member of the Team first needs to authorize it.

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.

Web: Feed optimistic write has no rollback on failed transaction — likes can appear for posts the user never liked

1 participant