Skip to content

feat(yield): Uniswap v3 yield rail + gas-aware auto-compound card - #19

Open
StSora wants to merge 21 commits into
mainfrom
feat/compound-interest
Open

feat(yield): Uniswap v3 yield rail + gas-aware auto-compound card#19
StSora wants to merge 21 commits into
mainfrom
feat/compound-interest

Conversation

@StSora

@StSora StSora commented Jul 25, 2026

Copy link
Copy Markdown

Ships the Uniswap v3 yield rail to production, plus the auto-compound
projection card on top of it.

  • Yield rail (feat/uniswap-yield-agent): pool discovery, "Delegate to
    agent" with 3 single-use delegations (approve / approve / mint), agent
    redeems on its own.
  • Auto-compound card (merged via feat(compounding): add auto-compound projection card to the Yield flow #18): gas-aware compounding projection in
    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.

@host-intuition-box

host-intuition-box Bot commented Jul 25, 2026

Copy link
Copy Markdown

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

StSora and others added 12 commits July 25, 2026 19:47
…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.
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.
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