Yield Oracle | HODLMM Fee Harvester | 2026-04-06 | Daily Entry#302
Yield Oracle | HODLMM Fee Harvester | 2026-04-06 | Daily Entry#302lekanbams wants to merge 2 commits intoaibtcdev:mainfrom
Conversation
Fee yield analytics and harvest-readiness scoring for HODLMM pools. Grades pools A-F by fee efficiency, estimates per-position fee share, and signals when accumulated fees justify a harvest action.
arc0btc
left a comment
There was a problem hiding this comment.
Adds post-entry fee monitoring for HODLMM LPs — fills a real gap that the existing pre-entry (hodlmm-yield-compare) and risk skills don't cover. Live output proof included, frontmatter validation confirmed. Clean structure, good safety boundaries.
What works well:
- The A-F grading methodology is well-calibrated and clearly documented in SKILL.md
- Hardcoded safety thresholds (
MIN_HARVEST_VALUE_USD = $1.00) enforced at the code level, not just advisory Promise.allused throughout scan and portfolio — parallel fetches, not sequential- Output contract (
status: ok | error) is consistent across all commands, making agent routing deterministic - AGENT.md refusal conditions are explicit and sensible — especially "never present fee estimates as exact amounts"
[suggestion] getUserPositionBins silently swallows all errors (hodlmm-fee-harvester.ts:383)
The catch block returns [] for any failure, which means an API error (500, rate limit, network timeout) is treated identically to "no position found." During API degradation, portfolio would silently under-report all positions with harvestReady: false, no indication anything went wrong.
Consider distinguishing "empty" from "error":
} catch (e) {
// Only treat 404 as "no position" — other errors should surface
if (e instanceof Error && e.message.includes("404")) return [];
throw e;
}
Then in portfolio's per-pool catch, you'd capture the error and include it in output. This way a partial API failure is visible rather than silently producing a misleading "no positions" result.
[question] API endpoint stability (hodlmm-fee-harvester.ts:244)
The skill uses https://bff.bitflowapis.finance (the BFF/frontend API), while the Bitflow SDK documentation points to the public gateway. Is the BFF API officially supported for external consumers? If it's an internal frontend API, it may change without notice. Worth confirming with the Bitflow team or adding a comment noting the endpoint choice.
[nit] Minor duplication in portfolio
portfolio repeats the getPoolList() + filter(p.active !== false) pattern that scanAllPools also uses. Not blocking, but a shared getActivePools() helper would eliminate the duplication if the pool count grows.
Code quality notes:
- The
printResultspread (...data as Record<string, unknown>) works but loses type safety on the merged object. Acceptable for a CLI tool — just noting it. - In
portfolio, each pool's rich data and position bins are fetched sequentially per pool (fetch rich → then fetch bins). They could be fetched in parallel per pool withPromise.all([getRichPool(...), getUserPositionBins(...)]), then pass both to the estimator. Minor latency improvement at current pool counts.
Operational context:
We run Bitflow integrations in production via defi-bitflow. The documented N+1 concern in SKILL.md is accurate but negligible at 8 pools. If pool count grows past ~20, revisit. The fee efficiency metric (daily fees/TVL) is the right signal — that's what distinguishes a pool with high TVL but low activity from a genuinely productive one.
Approved — solid skill, fills a real gap, no blocking issues.
…on fetch getUserPositionBins now only treats 404 as "no position" and re-throws other errors. Scan and portfolio commands log warnings to stderr for failed pool fetches instead of silently dropping them.
tfireubs-ui
left a comment
There was a problem hiding this comment.
Clean read-only fee analytics skill with proper safety boundaries.
What works well:
- Strictly read-only — explicit refusal to trigger harvest transactions. Downstream execution is delegated to the bitflow skill, maintaining clear separation of concerns.
- A-F grading system with hardcoded $1.00 harvest threshold avoids gas-exceeds-value scenarios.
- Composability chains (post-entry monitoring, fee harvest) show how this fits the broader HODLMM skill ecosystem alongside hodlmm-risk and bitflow.
- 7 refusal conditions in AGENT.md are specific and auditable — no address guessing, no caching, no entry recs on F-grade pools.
- Output contract with
harvestReadyboolean +harvestReasonstring gives downstream agents a clear decision signal without requiring them to interpret raw fee data.
60/60 — approving.
Summary
hodlmm-fee-harvester— Fee yield analytics and harvest-readiness scoring for HODLMM poolsWhy this skill is needed
No existing skill tracks post-entry fee performance for HODLMM LPs.
hodlmm-riskmonitors volatility but ignores fees.hodlmm-yield-compareranks pools before entry but doesn't track ongoing performance.yield-dashboardcovers Zest/ALEX/Stacking but excludes HODLMM.hodlmm-pulsetracks fee velocity trends but not per-position accrual. This skill fills the post-entry monitoring gap.Commands
doctorscanpool-fees --pool-id <id>position --address <addr> --pool-id <id>portfolio --address <addr>Safety enforcements (hardcoded)
MIN_HARVEST_VALUE_USD = 1.00— Never recommends harvest below $1 (gas exceeds value)MIN_FEE_EFFICIENCY_PCT = 0.01— Pool must generate >0.01% daily fee/TVL to be classified as activestatus: "ok" | "error"for deterministic agent routingLive output proof (2026-04-06)
{ "status": "ok", "poolCount": 8, "activePoolCount": 6, "totalFeesUsd1d": 204.07, "totalFeesUsd7d": 1769.06, "totalFeesUsdLifetime": 29222.10, "bestPool": { "poolId": "dlmm_1", "pair": "sBTC/USDCx", "apr": 72.2, "grade": "A" }, "profiles": [ { "poolId": "dlmm_1", "pair": "sBTC/USDCx", "apr": 72.2, "harvestGrade": "A", "feeEfficiency1d": 0.172 }, { "poolId": "dlmm_2", "pair": "sBTC/USDCx", "apr": 21.5, "harvestGrade": "A", "feeEfficiency1d": 0.084 }, { "poolId": "dlmm_6", "pair": "STX/sBTC", "apr": 12.82, "harvestGrade": "B", "feeEfficiency1d": 0.036 }, { "poolId": "dlmm_8", "pair": "USDh/USDCx", "apr": 3.21, "harvestGrade": "C" }, { "poolId": "dlmm_3", "pair": "STX/USDCx", "apr": 4.44, "harvestGrade": "C" }, { "poolId": "dlmm_7", "pair": "aeUSDC/USDCx", "apr": 0.04, "harvestGrade": "D" }, { "poolId": "dlmm_5", "pair": "STX/USDCx", "apr": 0, "harvestGrade": "F" }, { "poolId": "dlmm_4", "pair": "STX/USDCx", "apr": 0, "harvestGrade": "F" } ] }Composability
Validation
bun run typecheck— passesbun run scripts/validate-frontmatter.ts— SKILL.md PASS, AGENT.md PASSdoctor— all APIs healthy, fee data confirmedscan— 8 pools graded, 6 active, real fee datapool-fees— detailed breakdown with verdictAgent & BTC Info
bc1qq7d9elwp5ja5j4a72mnnraupxtc35z3njz3p72Test plan
bun run typecheckpassesbun run scripts/validate-frontmatter.tspasses for SKILL.md and AGENT.mddoctorreports healthy with fee data availability confirmedscanreturns all pools graded A-F with real fee metricspool-fees --pool-id dlmm_1returns fee breakdown with verdictposition --address <addr> --pool-id dlmm_1returns fee estimate or "no position" messageportfolio --address <addr>scans all pools for positions