Repository navigation
fix(relayer,dashboard): relay a gasless vote once; no 500 or error toast after it lands #2171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
bd4f072
fix(relayer): answer simulated vote and delegation reverts with 409 S…
alextnetto 0b31859
fix(dashboard): say the vote is already counted and reload on every m…
alextnetto f36bb0a
fix(dashboard): relay a gasless vote once and never report a relayed …
alextnetto 913ba03
fix(dashboard): address review on the gasless vote flow
alextnetto File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| "@anticapture/relayer": patch | ||
| "@anticapture/gateful": patch | ||
| "@anticapture/dashboard": patch | ||
| --- | ||
|
|
||
| Answer a gasless vote or delegation that would revert on-chain (a vote already cast, a used nonce) with 409 SIMULATION_FAILED instead of 500 INTERNAL, documented in the relay routes Gateful exposes, and make a gasless vote reach the relayer once: the dashboard checks hasVoted before asking for a signature, confirms the relayed transaction on the DAO's chain instead of through the wallet, never reports a relayed vote as failed, and keeps the vote's submission state across modal closes and remounts so the ballot is not offered again | ||
35 changes: 35 additions & 0 deletions
35
apps/dashboard/features/governance/components/modals/VoteAlreadyCastContent.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import { CheckCircle2 } from "lucide-react"; | ||
|
|
||
| import { Button } from "@/shared/components"; | ||
|
|
||
| interface VoteAlreadyCastContentProps { | ||
| onClose: () => void; | ||
| } | ||
|
|
||
| /** | ||
| * The governor already holds a vote from this address, so the ballot on | ||
| * screen was never cast. Ends the flow with a way out rather than the ballot, | ||
| * which could only send the same refusal again. | ||
| */ | ||
| export const VoteAlreadyCastContent = ({ | ||
| onClose, | ||
| }: VoteAlreadyCastContentProps) => ( | ||
| <div className="flex flex-col items-center gap-3 px-4 py-8"> | ||
| <div className="bg-surface-opacity-success flex size-12 items-center justify-center rounded-full"> | ||
| <CheckCircle2 className="text-success size-6" /> | ||
| </div> | ||
|
|
||
| <h3 className="text-primary text-center text-lg font-medium"> | ||
| You have already voted on this proposal | ||
| </h3> | ||
|
|
||
| <p className="text-secondary max-w-sm text-center text-sm leading-5"> | ||
| Your earlier vote is the one that counts. It shows on this page once it is | ||
| indexed. | ||
| </p> | ||
|
|
||
| <Button variant="outline" onClick={onClose}> | ||
| Close | ||
| </Button> | ||
| </div> | ||
| ); |
52 changes: 52 additions & 0 deletions
52
apps/dashboard/features/governance/components/modals/VotePendingContent.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| import { ExternalLink, Hourglass } from "lucide-react"; | ||
| import type { Hash } from "viem"; | ||
|
|
||
| import { InlineAlert } from "@/shared/components/design-system/alerts/inline-alert/InlineAlert"; | ||
|
|
||
| interface VotePendingContentProps { | ||
| hash: Hash | null; | ||
| explorerBaseUrl?: string; | ||
| } | ||
|
|
||
| const shortenHash = (hash: string) => `${hash.slice(0, 10)}…${hash.slice(-8)}`; | ||
|
|
||
| /** | ||
| * A vote that may be on-chain but could not be confirmed here. It offers no | ||
| * way to vote again: the wallet would sign the same ballot, and the relayer | ||
| * would only be asked to replay it. | ||
| */ | ||
| export const VotePendingContent = ({ | ||
| hash, | ||
| explorerBaseUrl, | ||
| }: VotePendingContentProps) => ( | ||
| <div className="flex flex-col items-center gap-3 px-4 py-8"> | ||
| <div className="bg-surface-contrast flex size-12 items-center justify-center rounded-full"> | ||
| <Hourglass className="text-secondary size-6" /> | ||
| </div> | ||
|
|
||
| <h3 className="text-primary text-center text-lg font-medium"> | ||
| Your vote was sent | ||
| </h3> | ||
|
|
||
| {hash && explorerBaseUrl && ( | ||
| <a | ||
| href={`${explorerBaseUrl}/tx/${hash}`} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="text-link inline-flex items-center gap-1 text-sm leading-5 hover:underline" | ||
| > | ||
| {shortenHash(hash)} | ||
| <ExternalLink className="size-3.5 shrink-0" /> | ||
| </a> | ||
| )} | ||
|
|
||
| <InlineAlert | ||
| variant="warning" | ||
| text={ | ||
| hash | ||
| ? "It is not confirmed yet. Follow it on the explorer. This page shows your vote on its own once it is indexed, so there is no need to vote again." | ||
| : "The relayer did not answer clearly, so the vote may already be on its way. This page shows your vote on its own once it is indexed, so there is no need to vote again." | ||
| } | ||
| /> | ||
| </div> | ||
| ); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new documented 409 responses in the relay controllers change the relayer OpenAPI contract that
mergeRelayerPathsexposes through Gateful, but this changeset bumps only the relayer and dashboard. Add an@anticapture/gatefulentry so the aggregated API contract is versioned and released consistently.AGENTS.md reference: AGENTS.md:L121-L124
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 913ba03: the changeset now bumps
@anticapture/gatefultoo, since the relay routes it exposes document the new 409.