Skip to content

feat: optimistic UI updates and rollback for node staking adjustments#86

Merged
JamesEjembi merged 2 commits into
VeriNode-Labs:mainfrom
real-venus:feat/optimistic-staking-updates
Jun 25, 2026
Merged

feat: optimistic UI updates and rollback for node staking adjustments#86
JamesEjembi merged 2 commits into
VeriNode-Labs:mainfrom
real-venus:feat/optimistic-staking-updates

Conversation

@real-venus

Copy link
Copy Markdown
Contributor

Closes: #5

What changed

State — src/store/stakingStore.ts

  • Rewrote the store into an optimistic engine holding optimisticBalance and a
    pending[] list of in-flight operations.
  • Each entry carries optimisticTxId (UUID v4), action, amount, the mapped
    realTxHash, status, and a decoded error.
  • Persisted to sessionStorage via zustand persist middleware, so optimistic
    state survives component remounts / tab navigation. SSR-safe storage guard included.
  • Balance changes are delta-based (stake/restake/delegate decrease,
    unstake/undelegate increase), so rollback is the exact inverse and composes
    correctly with concurrent operations.

Hook — src/hooks/useSorobanStaking.ts

  • Exposes stake / unstake / restake / delegate / undelegate, plus
    retry(optimisticTxId), pending, pendingCount, and balance.
  • Lifecycle per action: (a) apply optimistic delta synchronously, (b) mint
    optimisticTxId, (c) submit → real transactionHash, (d) store the
    optimisticTxId → realTxHash mapping, then poll for finality.
  • On confirm: marks confirmed + success toast with a Stellar explorer link.
    On failure/30s timeout: rolls the balance back, error toast, and logs to Sentry
    with the optimisticTxId for traceability.
  • retry() drops the failed entry and re-enters the optimistic lifecycle with the
    same parameters.

Restructure useSorobanStaking into a per-action state machine
(idle -> pending (optimistic) -> confirmed | failed) so stake
adjustments feel instant despite 6-30s Soroban finality.

- stakingStore: optimistic balance + pending[] state machine, persisted
  to sessionStorage so it survives tab navigation / component remounts
- useSorobanStaking: stake/unstake/restake/delegate/undelegate apply the
  balance delta synchronously, submit via the staking API, await finality,
  then confirm or roll back on failure/timeout (30s); logs failures to
  Sentry with the optimisticTxId; exposes pending + retry()
- lib/stellar/transaction: deterministic staking transaction builder
- lib/api/staking: submitStake/... wrapping the builder + Soroban RPC,
  returning the real transactionHash and decoding errors
- StakingPendingIndicator: animated in-flight pulse, explorer link,
  retry button for failed operations
- vitest + msw test: stake(100) applies optimistically, reverts on a
  failed on-chain execution, and re-applies optimistically on retry()
- update session watcher + global types for the new store shape
@JamesEjembi

Copy link
Copy Markdown
Contributor

@real-venus resolve conflicts

@real-venus

Copy link
Copy Markdown
Contributor Author

@real-venus resolve conflicts

Now I am working on it.

Resolve conflicts from the pre-flight fee + XSS-sanitization work that
landed on main:

- src/lib/stellar/transaction.ts: union both modules — upstream's
  buildTransaction/computeFee (pre-flight fee estimation) plus this
  branch's buildStakingTransaction (optimistic staking envelope)
- vitest.config.ts: keep upstream's node-environment config; the
  optimistic-staking suite opts into jsdom via a per-file
  `// @vitest-environment jsdom` docblock
- package.json: keep upstream's test:unit / lint:colors scripts and add
  jsdom + msw devDeps; vitest bumped to ^3.2.4
- package-lock.json: regenerated against the merged manifest
@real-venus

Copy link
Copy Markdown
Contributor Author

@JamesEjembi

Fixed.

@JamesEjembi JamesEjembi 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.

LGTM

@JamesEjembi JamesEjembi merged commit f2341ba into VeriNode-Labs:main Jun 25, 2026
2 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.

2 participants