diff --git a/app/api/dao-overview/route.ts b/app/api/dao-overview/route.ts index b664898..d5fdd5f 100644 --- a/app/api/dao-overview/route.ts +++ b/app/api/dao-overview/route.ts @@ -156,6 +156,12 @@ async function readLightchainOverview(pub: Pub) { rawSupplyWei != null && votableWei != null && (rawSupplyWei as bigint) > (votableWei as bigint) ? (rawSupplyWei as bigint) - (votableWei as bigint) : null; + // Castable = votable minus LCAI held by protocol contracts that can't vote + // (Treasury + FeePool). votes == balance on the precompile, so their balances + // are their (non-castable) voting power. + const nonCastableWei = treasuryWei + feePoolWei; + const castableWei = + votableWei != null && (votableWei as bigint) > nonCastableWei ? (votableWei as bigint) - nonCastableWei : null; return { treasuryWei: treasuryWei.toString(), feePoolWei: feePoolWei.toString(), @@ -164,6 +170,9 @@ async function readLightchainOverview(pub: Pub) { // The actual quorum threshold + the staked-excluded base it applies to. quorumWei: quorumWei != null ? (quorumWei as bigint).toString() : null, votableSupplyWei: votableWei != null ? (votableWei as bigint).toString() : null, + // Castable = votable minus the non-votable contract holdings (Treasury/FeePool). + castableSupplyWei: castableWei != null ? castableWei.toString() : null, + nonCastableWei: nonCastableWei.toString(), rawSupplyWei: rawSupplyWei != null ? (rawSupplyWei as bigint).toString() : null, stakeExcludedWei: stakeExcludedWei != null ? stakeExcludedWei.toString() : null, stakeExcludedFromQuorum: true as boolean, diff --git a/app/build/dao/treasury-bar.tsx b/app/build/dao/treasury-bar.tsx index 6760f42..99a315b 100644 --- a/app/build/dao/treasury-bar.tsx +++ b/app/build/dao/treasury-bar.tsx @@ -31,26 +31,37 @@ interface Overview { rawSupplyWei?: string | null; stakeExcludedWei?: string | null; holderCount?: number | null; + // Votable minus non-votable contract holdings (Treasury/FeePool) = castable. + castableSupplyWei?: string | null; + nonCastableWei?: string | null; schedule?: Schedule; error?: string; } const VOTE_SYMBOL: Record = { ethereum: "LCAIB", lightchain: "LCAI" }; -/** LightChain voting-power summary: votable sum, accounts, staked-excluded. */ +/** LightChain voting-power summary: castable vs votable, staked-excluded, accounts. */ function VotingPowerLine({ chain, data }: { chain: DaoChain; data: Overview }) { if (!data.votableSupplyWei) return null; const sym = VOTE_SYMBOL[chain]; const votable = formatLcaiWei(BigInt(data.votableSupplyWei), 0); + // Castable = votable minus the Treasury/FeePool (contracts that can't vote). + const castable = data.castableSupplyWei ? formatLcaiWei(BigInt(data.castableSupplyWei), 0) : null; + const nonCastable = data.nonCastableWei && BigInt(data.nonCastableWei) > 0n ? formatLcaiWei(BigInt(data.nonCastableWei), 0) : null; const accounts = data.holderCount != null ? `~${data.holderCount.toLocaleString()} accounts` : null; const excluded = data.stakeExcludedWei && BigInt(data.stakeExcludedWei) > 0n - ? `${formatLcaiWei(BigInt(data.stakeExcludedWei), 0)} ${sym} staked (excluded from quorum)` + ? `${formatLcaiWei(BigInt(data.stakeExcludedWei), 0)} ${sym} staked (excluded)` : null; return (

- Voting power: {votable} {sym} votable - {accounts ? <> across {accounts} : null} + Voting power:{" "} + {castable ? ( + <>{castable} {sym} castable of {votable} votable{nonCastable ? <> ({nonCastable} in the treasury, non-votable) : null} + ) : ( + <>{votable} {sym} votable + )} {excluded ? <> · {excluded} : null} + {accounts ? <> · {accounts} : null}

); }