8000 Full Transparency to Voting History feature to be implemented within the Livepeer Explorer by liamdoyle95 · Pull Request #300 · livepeer/explorer · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Full Transparency to Voting History feature to be implemented within the Livepeer Explorer #300

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

Open
wants to merge 38 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
78021a1
init setup
liamdoyle95 Mar 31, 2025
157d853
Intergration
liamdoyle95 Mar 31, 2025
1979dbd
Test data is fetching and renders
liamdoyle95 Apr 1, 2025
77bda06
Temp limit to fetches and updated UI
liamdoyle95 Apr 1, 2025
15d3ff6
updated styling to Livepeer CSS
liamdoyle95 Apr 2, 2025
e64faa6
Total Votes added
liamdoyle95 Apr 2, 2025
bab08c0
voting popover logic
liamdoyle95 Apr 3, 2025
1e9ab0d
Fix
liamdoyle95 Apr 3, 2025
b3cd403
Voting Popover UI fix
liamdoyle95 Apr 3, 2025
4337560
Fetches most recent ENS name
liamdoyle95 Apr 7, 2025
8b28694
ENS name fix and link
liamdoyle95 Apr 8, 2025
d12df34
Loading Spinner, ENS and Popover
liamdoyle95 Apr 8, 2025
57284a8
formatAddress
liamdoyle95 Apr 10, 2025
ae01af4
Address for popover
liamdoyle95 Apr 10, 2025
48da46b
Removed on popover
liamdoyle95 Apr 11, 2025
0334e3a
remove qodo
liamdoyle95 Apr 16, 2025
b8904ac
.env.example
liamdoyle95 Apr 16, 2025
64ae030
queries, fetch votes, fomratAddress, chains moved to retrespective pl…
liamdoyle95 Apr 18, 2025
eafc541
cleanup: factor out duplicate vote so reusable between voting components
liamdoyle95 Apr 25, 2025
b5c5b42
Reduced duplicated code and fixed UX issue.
liamdoyle95 Apr 25, 2025
fb3f7a0
Missed link for mobile voter
liamdoyle95 Apr 25, 2025
c5634eb
Removed technical debt no longer needed. Added No Votes
liamdoyle95 Apr 26, 2025
6b53e24
Cleanup
liamdoyle95 Apr 26, 2025
2f8ede0
Vote hooks, hydration fix
liamdoyle95 May 3, 2025
b8299fd
treasuryProposals.ts file removed and queries moved into queries fold…
liamdoyle95 May 4, 2025
8d93c30
treasuryProposals within apollo
liamdoyle95 May 6, 2025
8b0f5a8
removed useVotes and optimised other hooks
liamdoyle95 May 6, 2025
0b4e58f
Only fetch Ens name for votes
liamdoyle95 May 10, 2025
3c4b760
more changes
May 13, 2025
37eb398
address import changes and typing
May 23, 2025
ec61856
useInfuraVoterVotes
liamdoyle95 May 23, 2025
db7bb3d
PR ready
liamdoyle95 May 28, 2025
18ee2f6
yarn restore
liamdoyle95 May 28, 2025
afeb09a
lint error fix
liamdoyle95 May 28, 2025
e51794f
fixed import and relative import errors
May 29, 2025
fbcd076
VoteTx, Padding UI
liamdoyle95 May 30, 2025
7e941a2
Merge branch 'AddVotingTransparency' of https://github.com/liamdoyle9…
liamdoyle95 May 30, 2025
2697e76
Table UI align left
liamdoyle95 May 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion @types/custom.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ declare module "*.svg" {
declare module "*.png";
declare module "*.jpg";
declare module "*.jpeg";
declare module "*.gif";
declare module "*.gif";
27 changes: 27 additions & 0 deletions apollo/treasuryProposals.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { gql } from "@apollo/client";

export const ENS_QUERY = gql`
query getENS($address: String!) {
domains(where: { resolvedAddress: $address }
orderBy: registration__registrationDate
orderDirection: desc
) {
name
resolvedAddress {
id
}
createdAt
}
}
`;

export const GET_PROPOSALS_BY_IDS = gql`
query getProposalsByIds($ids: [String!]!) {
treasuryProposals(where: { id_in: $ids }) {
id
description
voteStart
voteEnd
}
}
`;
2 changes: 1 addition & 1 deletion components/TreasuryVotingWidget/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useAccountAddress } from "hooks";
import numeral from "numeral";
import { useMemo } from "react";
import { abbreviateNumber, fromWei, shortenAddress} from "@lib/utils";
import VoteButton from "../VoteButton";
import VoteButton from "../Votes/VoteButton";
import { ProposalVotingPower } from "@lib/api/types/get-treasury-proposal";
import { ProposalExtended } from "@lib/api/treasury";
import QueueExecuteButton from "@components/QueueExecuteButton";
Expand Down
File renamed without changes.
106 changes: 106 additions & 0 deletions components/Votes/VoteDetail/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
"use client";

import React from "react";
import { Box, Heading, Text, Link, Badge } from "@livepeer/design-system";
import { ArrowTopRightIcon } from "@modulz/radix-icons";
import { VOTING_SUPPORT, Vote } from "@lib/api/types/votes";
import { formatAddress } from "utils/formatAddress";
import { formatLpt } from "@lib/utils";

interface VoteDetailItemProps {
vote: Vote;
}

const Index: React.FC<VoteDetailItemProps> = ({ vote }) => {
const support = VOTING_SUPPORT[vote.choiceID] || VOTING_SUPPORT["2"];
return (
<Box
css={{
backgroundColor: "$neutral4",
padding: "$4",
borderRadius: "$2",
marginTop: "$2",
}}
>
<Heading as="h2" css={{ fontSize: "$3", mb: "$2", color: "$white" }}>
<Link
href={`https://explorer.livepeer.org/treasury/${vote.proposalId}`}
target="_blank"
css={{
color: "$green11",
textDecoration: "none",
"&:hover": { textDecoration: "underline" },
}}
>
{vote.proposalTitle}
</Link>
</Heading>

<Text css={{ mb: "$1" }}>
& F438 lt;Text as="span" css={{ color: "$white", fontWeight: 600 }}>
Proposal ID:
</Text>{" "}
<Text as="span" css={{ color: "$neutral11" }}>
{formatAddress(vote.proposalId)}
</Text>
</Text>

<Text css={{ mb: "$1", display: "inline-flex", alignItems: "center" }}>
<Text
as="span"
css={{ color: "$white", fontWeight: 600, marginRight: "$1" }}
>
Support:
</Text>
<Text as="span" css={{ color: "$neutral11", ...support.style }}>
{support.text}
</Text>
</Text>

<Text css={{ mb: "$1" }}>
<Text as="span" css={{ color: "$white", fontWeight: 600 }}>
Weight:
</Text>{" "}
<Text as="span" css={{ color: "$neutral11" }}>
{formatLpt(vote.weight)}
</Text>
</Text>

<Text css={{ mb: "$1" }}>
<Text as="span" css={{ color: "$white", fontWeight: 600 }}>
Reason:
</Text>{" "}
<Text as="span" css={{ color: "$neutral11" }}>
{vote.reason || "No reason provided"}
</Text>
</Text>

<Box css={{ textAlign: "start", mt: "$2" }}>
{vote.transactionHash ? (
<Link
href={`https://arbiscan.io/tx/${vote.transactionHash}#eventlog`}
target="_blank"
=> e.stopPropagation()}
css={{
display: "inline-block",
transition: "transform 0.2s ease",
"&:hover": { transform: "scale(1.1)" },
}}
>
<Badge css={{ cursor: "pointer" }} variant="primary" size="1">
{formatAddress(vote.transactionHash)}
<Box
css={{ ml: "$1", width: 15, height: 15 }}
as={ArrowTopRightIcon}
/>
</Badge>
</Link>
) : (
<Text css={{ color: "$neutral9" }}>N/A</Text>
)}
</Box>
</Box>
);
};

export default Index;
77 changes: 77 additions & 0 deletions components/Votes/VoteModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React from "react";
import { createPortal } from "react-dom";
import { Box, Button } from "@livepeer/design-system";

interface VoteModalProps {
onClose: () => void;
children: React.ReactNode;
}

const Index: React.FC<VoteModalProps> = ({ onClose, children }) =>
createPortal(
<Box
css={{
position: "fixed",
inset: 0,
display: "flex",
alignItems: "center",
justifyContent: "center",
backgroundColor: "rgba(0, 0, 0, 0.5)",
backdropFilter: "blur(4px)",
zIndex: 9999,
}}
=> e.stopPropagation()}
>
<Box
css={{
position: "relative",
backgroundColor: "$neutral3",
borderRadius: "$2",
width: "90%",
maxHeight: "90vh",
display: "flex",
flexDirection: "column",
"@bp2": { width: "50%" },
}}
=> e.stopPropagation()}
>
<Box
css={{
position: "sticky",
top: 0,
right: 0,
zIndex: 10,
backgroundColor: "$neutral3",
px: "$4",
py: "$2",
display: "flex",
justifyContent: "flex-end",
}}
>
<Button
variant="gray"
css={{
"&:hover": { backgroundColor: "$red6" },
}}
>
>
Close
</Button>
</Box>

<Box
css={{
overflowY: "auto",
px: "$4",
py: "$2",
maxHeight: "calc(90vh - 56px)",
}}
>
{children}
</Box>
</Box>
</Box>,
document.body
);

export default Index;
37 changes: 37 additions & 0 deletions components/Votes/VotePopover/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use client';

import React from 'react';
import Spinner from '@components/Spinner';
import { Flex, Text } from '@livepeer/design-system';
import VoteModal from '../VoteModal';
import VoteDetail from '../VoteDetail';
import { useInfuraVoterVotes } from '../../../hooks/TreasuryVotes/useInfuraVoterVotes';

interface VoterPopoverProps {
voter: string;
onClose: () => void;
}

const Index: React.FC<VoterPopoverProps> = ({ voter, onClose }) => {
const { votes, isLoading } = useInfuraVoterVotes(voter);

return (
<VoteModal >
{isLoading ? (
<Flex css={{ justifyContent: 'center', alignItems: 'center', height: '150px' }}>
<Spinner />
</Flex>
) : votes.length > 0 ? (
votes.map((vote, idx) => (
<VoteDetail key={vote.transactionHash ?? idx} vote={vote} />
))
) : (
<Text css={{ color: '$neutral11', textAlign: 'center', mt: '$4' }}>
No votes found for this voter.
</Text>
)}
</VoteModal>
);
};

export default Index;
97 changes: 97 additions & 0 deletions components/Votes/VoteTable/Views/DesktopVoteTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from "react";
import { Box, Flex, Text } from "@livepeer/design-system";
import { Vote } from "../../../../lib/api/types/votes";
import { VoteView } from "./VoteItem";

export interface VoteTableProps {
votes: Vote[];
counts: { yes: number; no: number; abstain: number };
formatWeight: (weight: string) => string;
onSelect: (voter: string) => void;
}

export const DesktopVoteTable: React.FC<VoteTableProps> = ({
votes,
counts,
formatWeight,
onSelect,
}) => (
<Box
css={{ display: "none", "@bp2": { display: "block" }, overflowX: "auto" }}
>
<Text
css={{
textAlign: "center",
fontSize: "$3",
fontWeight: 500,
color: "$white",
mb: "$2",
}}
>
Vote Results
</Text>
<Flex
css={{
justifyContent: "center",
mb: "$4",
fontWeight: 700,
fontSize: "$3",
color: "$white",
}}
>
<Text css={{ mr: "$1", color: "$green9" }}>Yes ({counts.yes})</Text>
<Text>|</Text>
<Text css={{ mx: "$1", color: "$red9" }}>No ({counts.no})</Text>
<Text>|</Text>
<Text css={{ ml: "$1", color: "$yellow9" }}>
Abstain ({counts.abstain})
</Text>
</Flex>

<Text
css={{
textAlign: "center",
fontSize: "$2",
color: "$neutral11",
mb: "$2",
}}
>
Click on a vote to view a voters proposal voting history.
</Text>
<Box as="table" css={{ width: "100%", borderCollapse: "collapse" }}>
<Box as="thead">
<Box as="tr" css={{ backgroundColor: "$neutral4" }}>
{["Voter", "Support", "Weight", "Reason", "Vote Txn"].map((label) => (
<Box
key={label}
as="th"
css={{
textAlign: "left",
textTransform: "uppercase",
fontSize: "$1",
color: "$neutral11",
borderBottom: "1px solid $neutral5",
padding: "$2 $3",
}}
>
{label}
</Box>
))}
</Box>
</Box>
<Box as="tbody">
{votes.map((vote) => {
return (
<VoteView
key={vote.choiceID}
vote={vote}
>
formatWeight={formatWeight}
isMobile={false}
/>
);
})}
</Box>
</Box>
</Box>
);
Loading
0