Skip to content

feat: render and propose the offboard and set-parameters votes - #67

Open
haikoschol wants to merge 1 commit into
feat/registration-lookup-by-contract-idfrom
feat/sv-ui-offboarding-set-params
Open

haikoschol wants to merge 1 commit into
feat/registration-lookup-by-contract-idfrom
feat/sv-ui-offboarding-set-params

Conversation

@haikoschol

@haikoschol haikoschol commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Closes ChainSafe/canton-extending-mainnet#128.

Stacked on #68 (backend: registration lookup by contract id); please review that first. This PR contains only the SV UI.

Summary

The SV UI did not support the two dedicated-synchronizer votes that SVs cast by hand:

  • SRARC_ArchiveSynchronizerRegistration: offboards a synchronizer.
  • SRARC_SetSynchronizerGovernanceParameters: today, changes its discount.

Their vote pages failed with "Unsupported Action", their rows in the vote lists had no name, and neither vote could be proposed from the UI. This PR adds both, following the shape of #52 (RegisterSynchronizer), plus a compile-time check that every Daml vote action has a UI decision.

Both votes pin a registration by contract id, and that is all their payload carries, so the vote pages and forms rely on a backend lookup by contract id, added in #68. The issue calls itself UI only; that endpoint is the one exception. It does not change Daml, so it fits the 0.10.3 cut.

Backend

The contract-id lookup these pages and forms use is in #68, which this PR is stacked on.

SV UI

Vote lists and vote pages

  • Both votes have titles: "Offboard Dedicated Synchronizer" and "Set Dedicated Synchronizer Parameters".
  • A vote's page resolves the pinned contract id and shows the synchronizer id, the operator and the contract id. For set-parameters it also shows the current and proposed parameters side by side.
  • An open vote whose registration is no longer active shows a warning that executing it will fail. This covers the issue's stale-contract-id design point: a set-parameters vote recreates the registration under a new contract id, so any other open vote that pins the old one can no longer execute. Closed votes show no warning, because there an archived registration is expected.

Create-proposal forms

  • Both forms take a synchronizer id, resolve it through the SV app's registration lookup (feat(sv-ui): reject a synchronizer id that is already registered #59), and show the registration before the SV proposes.
  • The offboard form can also take a registration contract id. The lookup by synchronizer id returns only the lowest contract id, so this is the only way to reach the second of two duplicate registrations ([P2-E1.4] Registry uniqueness ChainSafe/canton-extending-mainnet#54).
  • A form rejects a registration that another open offboard or set-parameters vote already pins, since only one of them could execute.
  • A registration that can't be found is an error, as is a failed lookup, since without the lookup there is no contract id to target.
  • The set-parameters form starts from the registration's current values and requires at least one change. It builds the whole GovernanceParameters record from a field spec (governanceParameterFields.ts) that is typed over every field of the Daml record. A field added in Daml stops the build until it has an entry, so it can't be silently dropped.

Coverage check (utils/actionCoverage.ts)

  • Every DsoRules_ActionRequiringConfirmation and AmuletRules_ActionRequiringConfirmation tag is classified as either a UI vote or "no UI", and each "no UI" entry carries a reason.
  • Both records are exhaustive over the generated tag unions. A type-level assertion requires the UI votes to be exactly SupportedActionTag.
  • Adding or removing an action in Daml fails tsc until the action is classified. I checked this by adding a constructor to the generated types, and separately by dropping a tag from SupportedActionTag.

Testing

  • SV frontend: type:check, prettier/eslint and test:sbt are all green (307 tests).
    • New suites for both forms, modelled on register-synchronizer-form.test.tsx.
    • Vote-page cases for both actions: live registration, archived registration on an open vote, archived registration on a closed vote.
    • Review-summary cases and the create-proposal dropdown.
    • Regression tests for an edited parameter being overwritten when submitting re-runs the lookup.
  • Backend tests: see feat: look up a synchronizer registration by contract id #68.
  • Manual: on the local frontend-testing stack I registered, offboarded and set the parameters of a synchronizer through the SV UI.
Screenshot 2026-10-01 at 20 19 36 Screenshot 2026-10-01 at 20 20 31 Screenshot 2026-10-01 at 20 21 11

… [ci]

SRARC_ArchiveSynchronizerRegistration and
SRARC_SetSynchronizerGovernanceParameters were unsupported actions: their
vote pages failed with "Unsupported Action" and neither could be proposed.

- Both render in the vote lists and on their page, showing the synchronizer
  id and operator of the pinned registration, and for set-parameters the
  current and proposed parameters side by side. An open vote whose
  registration is no longer active says so, since executing it would fail.
- Both can be proposed. Each form resolves a synchronizer id through the SV
  app's registration lookup and shows the registration before proposing;
  the offboard form also takes a registration contract id, to reach a
  duplicate. A form rejects a registration another open vote already pins.
- The set-parameters form states the whole GovernanceParameters record,
  from a field spec that stops compiling when Daml adds a field.
- actionCoverage.ts classifies every DsoRules and AmuletRules vote action as
  a UI vote or not, exhaustively over the generated tag unions, and requires
  the UI votes to be exactly SupportedActionTag. Adding an action in Daml
  fails the frontend type check until it is classified.

Signed-off-by: Haiko Schol <haiko@chainsafe.io>
@haikoschol haikoschol self-assigned this Oct 1, 2026

@moritzkiefer-da moritzkiefer-da left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the pr! overall looks sensible but let's please split the backend changes into a separate pr and then stack the frontend changes on top of it for easier review

@haikoschol
haikoschol changed the base branch from main to feat/registration-lookup-by-contract-id October 2, 2026 08:50
@haikoschol

Copy link
Copy Markdown
Collaborator Author

Thanks! Split as suggested: the backend (Scan + SV app lookup by contract id) is now #68, and this PR is stacked on it and contains only the SV UI.

This branch has not been deployed

No deployments
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.

[P2-E1.7] SV UI renders and proposes the offboard and set-parameters votes

2 participants