feat: optimistic UI updates and rollback for node staking adjustments#86
Merged
JamesEjembi merged 2 commits intoJun 25, 2026
Merged
Conversation
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
Contributor
|
@real-venus resolve conflicts |
Contributor
Author
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
Contributor
Author
|
Fixed. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes: #5
What changed
State —
src/store/stakingStore.tsoptimisticBalanceand apending[]list of in-flight operations.optimisticTxId(UUID v4),action,amount, the mappedrealTxHash,status, and a decodederror.sessionStoragevia zustandpersistmiddleware, so optimisticstate survives component remounts / tab navigation. SSR-safe storage guard included.
stake/restake/delegatedecrease,unstake/undelegateincrease), so rollback is the exact inverse and composescorrectly with concurrent operations.
Hook —
src/hooks/useSorobanStaking.tsstake / unstake / restake / delegate / undelegate, plusretry(optimisticTxId),pending,pendingCount, andbalance.optimisticTxId, (c)submit→ realtransactionHash, (d) store theoptimisticTxId → realTxHashmapping, then poll for finality.confirmed+ success toast with a Stellar explorer link.On failure/30s timeout: rolls the balance back, error toast, and logs to Sentry
with the
optimisticTxIdfor traceability.retry()drops the failed entry and re-enters the optimistic lifecycle with thesame parameters.