fix(#611): dual_stacking_status APR/cycle tuple decode#621
Conversation
cvToJSON returns nested tuple .value with MIN_APR/MAX_APR wire keys. Read unwrapped keys so APR and cycleOverview are non-zero. Closes aibtcdev#611
arc0btc
left a comment
There was a problem hiding this comment.
Fixes the dual_stacking_status APR/cycle-overview zeroing bug (#611) — cvToJSON wraps tuple fields under .value with wire keys like MIN_APR/MAX_APR/cycle-id, and the old code was reading min-apr directly off the top-level object, so every field silently came back undefined → 0.
What works well:
- Good process fix from the predecessor PR: #617 (closed) accidentally carried the entire unmerged #613 asset-selection diff on top of its own commits because it branched off an unmerged feature branch. This PR is a single clean commit, scoped exactly to the #611 tuple-decode fix — confirmed via
gh pr view --json commits. tupleFields()/fieldValue()correctly unwrap the{type, value: {KEY: {type, value}}}shape and verified against real Clarity wire bytes in the new test (APR_HEX/OVERVIEW_HEX), not just a hand-built mock object — that's a meaningfully stronger test than the usual JSON-fixture approach.- The
warningsarray (existing pattern from #554) is extended sensibly: a decode failure now surfaces as"...tuple decoded but MIN_APR/MAX_APR keys missing"instead of silently reporting 0% APR, which is exactly the kind of failure mode #611 was about. - Comment on
tupleFieldsexplaining the wire-key mismatch (line 134-137) is genuinely useful — names the specific bug it prevents.
[suggestion] Test verifies a mirror, not the shipped code (tests/unit/dual-stacking-tuple-decode.test.ts:5-21 vs src/tools/dual-stacking.tools.ts:138-159)
tupleFields/fieldValue are defined as local consts inside the dual_stacking_status handler closure, so the test can't import them — it re-implements a byte-for-byte copy instead. Both copies pass today, but if the source implementation changes later (e.g. someone tweaks the key fallback list) without updating the test's copy in lockstep, the test keeps passing while the shipped code silently regresses — which is the exact failure mode this PR exists to fix. Since neither function closes over per-request state, pulling them out to module scope (or a small dual-stacking-decode.ts util) and importing them in the test would make this a real regression test instead of a parallel implementation test.
[nit] The fallback key lists ("MIN_APR", "min-apr", "minApr") keep the old, now-confirmed-wrong keys as fallbacks. Harmless since MIN_APR matches first, but worth a short comment noting they're kept only as a defensive fallback in case Hiro ever returns an alternate shape — otherwise a future reader might assume min-apr is a real observed variant rather than dead weight from the bug this PR fixes.
Code quality notes:
- The
minimumEnrollmentSatsprimitive-vs-object branch (lines 224-229) is unrelated to the tuple-decode bug —get-minimum-enrollment-amountreturns a plain uint CV, not a tuple. It's harmless defensive coding but slightly expands the PR's stated scope; not blocking.
Operational context: We don't run this MCP server ourselves, so no first-hand production data on this endpoint, but the warnings-array pattern here (added in #554, extended in this PR) is the right shape — degrade per-field instead of failing the whole tool call, and surface why a field is zero rather than reporting a misleading value.
Approving — the fix is correct and verified against real wire bytes, the process issue from #617 was properly addressed, and the one real suggestion (test importing real code) is a follow-up, not a blocker.
Pull tupleFields/fieldValue to dual-stacking-decode.ts so tests import the shipped code (review follow-up on aibtcdev#621) instead of a parallel mirror.
|
Addressed review suggestion: extracted `tupleFields` / `fieldValue` to `src/tools/dual-stacking-decode.ts` and updated the unit test to import the shipped helpers (no more parallel mirror). Also noted that `min-apr`/`minApr` fallbacks are defensive only. |
Summary
Fixes #611 (re-submit of closed #617 dual-stacking portion only).
cvToJSONreturns tuple fields under.valuewith wire keys likeMIN_APR/MAX_APR. The tool was reading the wrong shape, so APR and cycle overview showed zeros.Changes
.valueand map wire keysTest plan
dual_stacking_statusagainst mainnet shows non-zero APR when enrolled data existsCloses #611