feat(yield): Uniswap v3 yield rail + gas-aware auto-compound card - #19
Open
StSora wants to merge 21 commits into
Open
feat(yield): Uniswap v3 yield rail + gas-aware auto-compound card#19StSora wants to merge 21 commits into
StSora wants to merge 21 commits into
Conversation
…agent # Conflicts: # src/config/uniswap.ts
add auto-compound projection card to the Yield flow
|
The preview deployment for Hourglass is ready. 🟢 Open Preview | Open Build Logs | Open Application Logs Last updated at: 2026-07-25 22:03:53 CET |
…rrect benefit-aware gate
Rework the auto-compound card so the projection is correct and the operator
can choose how the cadence is decided.
Gate fix (the important one):
- The old gate compounded whenever accrued fees >= 10x gas, ignoring whether
compounding actually beat holding. At low APR that over-compounded and
burned gas, so auto-compound could show LESS than hold (the "-$117.97
extra" bug).
- The gate is now benefit-aware: compound only when the marginal yield those
fees earn over the remaining horizon exceeds the gas. Result is always
>= holding, and the cadence scales with size and APR.
- Dropped the 10% performance fee from the head-to-head projection (it was
charged only on the compound side, an unfair comparison; fees are separate
accounting).
Cadence modes:
- Agent (default): the gas-aware gate decides when; shows "next compound
~in X days".
- Manual: the operator picks a fixed interval (weekly / monthly / quarterly);
compounds on that schedule. A too-tight schedule can lose to gas, which the
card surfaces honestly in red ("lost to gas") — demonstrating why Agent mode
is better.
Pool binding:
- The card takes the selected pool and shows it ("Reinvest fees into
WETH/USDC 0.30%"); the projection uses that pool's APR. The compound
delegation (next piece) will be pinned to this position.
Files:
- src/lib/compounding.ts: benefit-aware shouldCompound(accrued, remainingDays,
config), compoundBenefit, compoundThreshold, projectManual, and an optional
intervalDays on projectionCurve.
- src/ui/CompoundProjection.tsx: agent/manual toggle, interval selector, pool
label, mode-aware projection and sparkline.
- src/pages/Yield.tsx: passes the selected pool label.
- test/unit/compounding.test.ts: "never below hold" invariant + manual-mode
loss case.
Verified: tsc -b clean; economics checked (agent >= hold across APRs/sizes;
manual weekly at 5% dips below hold as expected).
…re gas estimate, fix interval logic Polish the auto-compound card from review feedback: - Collapse to just the header + toggle when Auto-compound is Off. - Agent mode shows no schedule params — the agent picks the moment; the projection is a fixed 1Y forecast with "next compound ~in X days". Horizon and interval selectors are Manual-only. - Gas is a per-chain estimate (Base ~$0.15, mainnet ~$12, testnets ~cents) labelled "est." — a forecast assumption, not a quote. The agent reads real live gas at execution. (Replaces the hardcoded $0.15.) - Interval options are constrained to the projection window and clamped on change, fixing the "quarterly over 1 month = 0 compounds" case.
…uidity delegation
…l keeps only the schedule
…+ mark best manual interval
… + redeem wiring (scaffold)
Add skills/hourglass-agent/scripts/run-compound.ts — self-contained runner (mirrors run-dca.ts): loads the signed compound mandate from the plan JSON, discovers the Safe's v3 position tokenId, reads live value/APR/gas, gates with projectAgentOptimal, and redeems collect + increaseLiquidity atomically as the Safe. Harvests and reinvests only; never touches principal. Remove scripts/compound-agent.ts scaffold — its decision and redeem wiring are absorbed into the runner.
Add skills/hourglass-agent/scripts/run-compound.ts — self-contained runner (mirrors run-dca.ts): loads the signed compound mandate from the plan JSON, discovers the Safe's v3 position tokenId, reads live value/APR/gas, gates with projectAgentOptimal, and redeems collect + increaseLiquidity atomically as the Safe. Harvests and reinvests only; never touches principal. Removes the scripts/compound-agent.ts scaffold (absorbed). Export CompoundTerms next to the delegation in the plan (StoredCompoundDelegation), matching the DCA/limit-order recap pattern: the runner reads mode/intervalDays from the salt-verified terms instead of a COMPOUND_INTERVAL_DAYS env var, and rejects a tampered plan. Note the increaseLiquidity per-period cap in FUTURE.md.
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.
Ships the Uniswap v3 yield rail to production, plus the auto-compound
projection card on top of it.
agent" with 3 single-use delegations (approve / approve / mint), agent
redeems on its own.
the Yield window — hold vs auto-compound, next-compound cadence, effective
APY. Pure economics core in src/lib/compounding.ts (+ tests).
Deploys to hourglass.box (production) and gets a Coolify preview.
Note: bundles the full yield feature — coordinated with the yield author.