Skip to content

feat(minibf): add /governance/proposals endpoints - #1219

Draft
slowbackspace wants to merge 3 commits into
mainfrom
feat/minibf-governance-proposals
Draft

feat(minibf): add /governance/proposals endpoints#1219
slowbackspace wants to merge 3 commits into
mainfrom
feat/minibf-governance-proposals

Conversation

@slowbackspace

@slowbackspace slowbackspace commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Closes #1093
Closes #1098

What

Adds the two Blockfrost governance proposal lookups to MiniBF:

  • GET /governance/proposals/{tx_hash}/{cert_index}
  • GET /governance/proposals/{gov_action_id} — CIP-0129 bech32 id (gov_action1...), both the 33-byte form and the minimal 32-byte form (index 0, used by cexplorer)

Both share one lookup path: parse the id, read ProposalState for the lifecycle fields, and decode the original proposal tx from the archive for the action detail.

Mapping notes

Blockfrost copies these columns from db-sync, so db-sync source and the official test fixtures are the reference:

  • expiration = ledger expiresAfter + 1, which equals dolos ProposalState::expires_at().
  • db-sync stamps ratified_epoch and enacted_epoch with the same enactment-boundary epoch. Dolos stores the epoch before that boundary, so both fields map to ratified_epoch + 1 and stay null until the boundary passes.
  • dropped_epoch = canceled_epoch (competing action enacted), or expired_epoch + 1 — db-sync drops an expired proposal one epoch after it marks it expired (verified against the official fixtures).
  • governance_description is the ledger Aeson encoding of the submitted GovAction ({"tag": ..., "contents": ...}). The endpoint decodes the archived proposal tx to reproduce it exactly: guardrails script hash, lineage parent, and the conway pparams-update JSON names (stakePoolTargetNum, ...) per the cardano-ledger pparams-update.json golden. Ratios render as plain numbers when the fraction terminates, else as numerator/denominator objects, matching the ledger encoding.
  • When the archived tx is unavailable (pruned archive, pre-Conway update rows), governance_description is null and the type falls back to ProposalState.

Testing

  • Standard matrix per handler: happy path, 400, 404, 500, with a seeded ProposalState; plus unit tests for the description JSON, the ratio rendering, and the minimal CIP-0129 encoding.
  • cargo +nightly fmt, clippy --all-targets -D warnings, full workspace tests pass.
  • Official blockfrost-tests suite (preview): all 19 governance proposal fixture requests pass — every action type, both id forms per proposal, and both CIP-0129 encodings. Verified against a fully synced preview node running this change. Note: the current fixtures contain no ratified/enacted proposal, so the ratified/enacted mapping is grounded in db-sync source only.

🤖 Generated with Claude Code

Add the two Blockfrost proposal lookups:
- /governance/proposals/{tx_hash}/{cert_index}
- /governance/proposals/{gov_action_id} (CIP-0129)

Map ProposalState to the openapi Proposal model. Epoch semantics
follow db-sync: expiration = ledger expiresAfter + 1, and the
ratified/enacted/dropped/expired epochs are stamped at the enactment
boundary. The governance_description JSON mirrors the ledger Aeson
encoding that db-sync stores.

Closes #1093
Closes #1098
@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 82796988-3a26-423a-9c94-490ae6e26bc6

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

The official BF fixtures show detail we can not reconstruct from
ProposalState: the guardrails script hash and the ledger conway
pparams-update JSON names. Decode the original proposal tx from the
archive and build governance_description from the submitted GovAction.

Also per fixture evidence: db-sync drops an expired proposal one epoch
after it marks it expired, and the CIP-0129 minimal encoding (32-byte
payload, index 0) must parse.
Verified against the CIP text: hrp, 33-byte layout, single index
byte, and classic bech32 all match. Clarify in the parser comment
that the 32-byte form is an ecosystem shorthand, not part of the CIP.
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.

minibf: add /governance/proposals/<action> minibf: add /governance/proposals/<tx>/<index>

1 participant