Repository navigation
feat(web): predict flow with Foresight credits, slippage settings and a money-checked run - #1
Merged
Merged
Conversation
…ver answers completes from the batch the chain mined, and Try the rest signs nothing again Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…and what a taken nonce means Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d record and its progress Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t, spend any credits the manager covers, and preview the credits swap's loss The per-run credits cap and the refusal on the credits swap's loss are gone; the swap keeps its slippage floor, and previewCreditsSwap names the loss for Details. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n underlying, for Details Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…imeout wagmi's mock connector sends eth_sendTransaction with viem's default 10 s, which a fork executing a large batch outlasts; production wallets do not use this connector. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…onfig, so the dev wallet loads without the app's env Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e size in the run's record Measured on a Gnosis fork: ~0.57M per batch, ~1.25M per option, ~0.53M for the credits leg; the model counts 0.7M, 1.5M and 0.7M against half the latest block's gas limit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed when a shown plan changed beyond the trade slippage start(shown) compares each shown option's plan with the plan the pools give now; confirm() goes ahead against the plans it named, and stops again if they move once more. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…quote and loss for Details Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the swap's loss is shown rather than refused Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, as it may be the credits transfer Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… custom percent, with a high-value threshold per swap kind Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ops short of its estimate, the credits swap and its loss, custom slippage, and a changed move's figures before Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fore signing, and name the confirm Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…p's header, over its body, and confirm moved prices from its button Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he moved ones, and take slippage and the credits swap's quote from the visitor's settings Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ort option and the credits swap, at 1280 and 375 in both themes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ot a trade's Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…phone on its side has scrolled to its end Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ils showed Each batch re-reads the pools before it is built and stops at moved, with the new figures, when its plan differs from what the run is held to; confirm merges them in and resumes, mid-run included. The credits swap is held to the floor Details showed and its loss is re-quoted at every build; Details and the check plan the split from what that floor mints, not from the credits at par. An option shown no plan that now trades is moved, the moved tolerance is capped at the default slippage, and a batch is sized under the 2^24 per- transaction gas cap. Predict waits for the plans and the credits quote. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ne, and give the settings a Done An out-of-range entry keeps its text and error after the field is left and saves nothing. Custom slippage starts at 0.01%, warns under 0.1% on trades and 0.05% on the credits swap, and errors and warnings carry an icon. The credits swap's card shows only to a visitor with credits; the panel's fields scroll under a fade with a Done in the button's place, and Tab wraps at its edges. The buy budget's unread share constant is replaced by a property over every slippage setting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… way back At moved, Details opens on the changed figures, whose Before line takes the warning tone, the status line names the one market that moved, and Go back returns the form where nothing was signed. Details always names each kind's max slippage, Auto included, as a row that opens the settings, sums the pool fees across markets, and a credits swap losing 1% or more is said on the status line. Under the Settings title the X closes the settings, and the title enters as the panel does. A reverted batch names raising max slippage. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…entry, moved Details and Go back; redraw their snapshots The settings, moved and Details snapshots redraw for Done, the warning icon, the unit without a gap, the Auto row in Details and the summary opening on moved figures. A slippage row in folded Details is text, not a button the dialog's focus trap would stop on, and the reverted copy fits two lines at 320 px. Selectors name the footer's own button now that Done shares its class. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dits quote where no route swaps them A run that stops at moved after its deposit keeps the funds step it was pressed with, as running and halted runs do. Credits ticked with no credits route are never quoted, so the popup says they cannot be spent rather than leave Predict checking prices. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e same credits and slippage, and never under the live quote's floor Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…out of trading before it waits on the button Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ne on its first retry Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… stops at moved where the plan or the credits swap changed Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… chain or the gnosis fork with one command Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…en minutes pass, then asks first (R15-G4) A coded wallet error is read once; whatever the nonce says short of mined or taken, the send is held and its step halts at `held`. A retry within ten minutes reads the nonce again and signs nothing while it is unused. Past ten minutes the step halts at `resign` and the popup asks, with the button "Sign again", before the step is signed. A nonce taken by another transaction lets the hold go and the step is signed again on the next press. A node that names insufficient funds or a revert refused the send, so that is not held. The 4 s grace is gone. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…is dead, with Check again and Discard (R15-G9) The send behind a submitted step stays in the snapshot as `sent`, nonce included, until the step settles. When reconcile reports the hash unseen, the nonce is read: under another transaction it lets the hash go and the step is signed again on the next press; mined as the same transaction under another hash, the run waits on that one; pending or mined as this hash, it reads as pending. Still unused, the hash is kept at `unseen` (Check again, Discard) for ten minutes from the send, then the run asks before signing again, as a held send does. A stored hash with no nonce kept goes straight to the ask. driver.discard() lets go of the hash and throws the run away, only in those two states. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… receipt reads mined or reverted (R15-G14) Recovery reads the receipt of each submitted step of such a run and stores the step as confirmed or pending once it has one, so Close and the card's Discard forget the run. A hash with no receipt keeps the run stored. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e and the app's, so a lagging node never reuses one (R16-CL-3, CX-2) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…nothing and stops at wrong network or wallet, retryable (R16-CL-1) viem's ChainMismatchError and AccountNotFoundError, wagmi's connector errors and EIP-1193 4100/4900/4901 are raised before eth_sendTransaction, so no nonce can be in use. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…only if it still reads unused (R16-CX-1) Covers the held-send path through the step's canSkip and the unseen-hash path through a fresh reconcile. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…eld sends by their nonce, so Close and Discard can forget it (R16-CL-2, CX-3) Applies to a run naming other contracts and to one whose options differ from the session's. A send mined is stored confirmed; one whose nonce was taken, or stayed unused past the hold, is dropped; a hash stored with no send is dropped once no node knows it and the record is past the store's 72 h expiry. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…n runner test keeps its imports in one group Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…t waits out the hold and answers Sign again before the batch lands The batch's send is stored before its prompt opens, so the reload holds it for ten minutes as decided in R15-G4; the test failed at 08d80a7 expecting an immediate re-sign. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e send held, since it can follow a broadcast EIP-1193 4100/4900/4901 come from the wallet and can arrive after it broadcast (a WalletConnect session dropping). Only viem and wagmi's own pre-request errors now drop the hold; a coded answer settles by nonce like any other. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…Locks are missing or refused, and refuses the run when neither works The lease is keyed foresight.predict-lease.<flowId>, lasts 90 s, is renewed every 15 s, and is dropped on release and on pagehide. Another tab takes it only once it has run out. RunOwnership gains heldHere(flowId). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…, rather than naming another tab, and the card holds its Discard The driver reports 'prompt-open' when the claim is refused while this tab holds the run; the popup and the card both show "A wallet prompt from this page is still open. Answer it in your wallet." The card polls while it holds the run, so Discard comes back once the prompt is answered. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ses, since that popup's own driver still holds the run until it unmounts Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…on test Recovery and retry show the funding a Resume will spend; Try the rest keeps the held credits preview. A buy that grows keeps a proportional minimum. Uncertain sends keep their evidence: nonce-search exhaustion, Discard on a stale unseen status and the session close no longer release them; a replaced or cancelled step never reads as success; an interrupted xDAI mint read is redone before the batch. Storage reads no longer delete expired records; a stored run missing a planned step is refused. What reaches signing from the indexer is checked against chain and config: collateral decimals, canonical pools and their orientation, the parent matching the URL, child bounds and tokens. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… the popup lets go; mocks expose what session verification reads A recovered retry keeps the run's saved slippage instead of the global setting. Discard holds the run until its reconcile reads and deletion finish. Recovery gets its own credits-price line, since its credits checkbox is hidden. The mock Seer factory and market expose collateralToken() and wrappedOutcome(), so the localhost stack passes the on-chain session check. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016rFSsfe3nTwTKF5gcb6ELA
…n the hourly grid A young or busy session showed one point per option per hour, so a burst of trades folded into its last price. Each trade inside the drawn range now adds its own point; the hourly grid still fills quiet stretches. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016rFSsfe3nTwTKF5gcb6ELA
…epic Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016rFSsfe3nTwTKF5gcb6ELA
Ported from the parked 10-11 epic run branches; the behaviour is on the PR, these cases were not pinned. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016rFSsfe3nTwTKF5gcb6ELA
Ported from the parked 10-11 epic run branches; the behaviour is on the PR, these cases were not pinned. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016rFSsfe3nTwTKF5gcb6ELA
Ported from the parked 10-11 epic run branches; the behaviour is on the PR, these cases were not pinned. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016rFSsfe3nTwTKF5gcb6ELA
Ported from the parked 10-11 epic run branches; the behaviour is on the PR, these cases were not pinned. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016rFSsfe3nTwTKF5gcb6ELA
Ported from the parked 10-11 epic run branches; the behaviour is on the PR, these cases were not pinned. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016rFSsfe3nTwTKF5gcb6ELA
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pend on Expected values come from MINT_RATE_MARGIN_BPS, BATCH_GAS_SHARE_BPS, optionsPerBatch, buyBudgetShareBps, MOVED_TOLERANCE_BPS, PRICE_TOLERANCE_TICKS and QUOTE_DEADLINE_SECONDS instead of literals; batch sizing asserts the chosen size, not the search order. Refusals assert their departure reason; the Algebra fake validates readContract too and no longer asserts inside itself. The replacement cases join orchestrator.resume.test.ts. The getBlock latest-tag mutant is equivalent and no longer asserted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
What this adds
The predict flow for a session: a visitor sets estimates on the option cards, presses Predict, and one popup takes them from wallet to placed prediction. It creates a trade wallet if needed, adds funds (sDAI, xDAI, Foresight credits, or a mix), then trades every option's pools towards the visitor's estimates in batches.
Predict popup
Foresight credits
manager.execute(Swapr swap) →WXDAI.withdraw→GnosisRouter.splitFromBasewith native value, inside onebatchValueExecute.yarn simulate:credits:gnosis-forkgrants test credits.Money safety
How it was tested
yarn workspace web test(vitest): 2,063 passed.yarn test:fork(money ledger on a gnosis fork): 29/29.predict-fork.spec.ts,predict-fork-credits.spec.ts): 7/7.Worth knowing
leftOut,slippage,optionsPerBatch,fromBlock. Runs stored by older builds are not migrated.splitFromBaseis the only call allowed to carry native value.SeerCreditsandCreditsManagerare vendored underpackages/contracts/contracts/vendor/trading-creditsfor the local mock. They pull in solmate (AGPL-3.0) as a dev dependency.test:forkuses the newest indexed session with pools near 0.5. Re-seed withyarn simulate:session:gnosis-forkthenyarn simulate:liquidity:gnosis-fork.Follow-ups (filed, not in this PR)
assertSwapExecutableguard is a no-op for Wrapped1155 outcome tokens.🤖 Generated with Claude Code