Skip to content

Commit

Permalink
Merge pull request #8 from NikosFotiadis/geat/vote-page
Browse files Browse the repository at this point in the history
Geat/vote page
  • Loading branch information
NikosFotiadis authored Nov 18, 2023
2 parents 19df475 + 5d8ba69 commit a500149
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 157 deletions.
5 changes: 3 additions & 2 deletions packages/nextjs/components/AccountAbstractionAttestations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import { getAttestationsForAddress } from "~~/services/web3/attestationService";

interface ScanComponentProps {
aaAddress: string;
eoaAddress: string;
}

const AccountAbstractionAttestations: React.FC<ScanComponentProps> = props => {
const { aaAddress } = props;
const { aaAddress, eoaAddress } = props;

const {
data = [],
Expand Down Expand Up @@ -39,7 +40,7 @@ const AccountAbstractionAttestations: React.FC<ScanComponentProps> = props => {
<div className="min-w-0 flex-auto">
<p className="text-xs font-medium leading-6 text-gray-600">Event Name</p>
<p className="text-xl font-semibold leading-6 text-gray-900">
<Link href={`/events/${attestation.eventId}`}>{attestation.eventName}</Link>
<Link href={`/user/${eoaAddress}/event/${attestation.eventId}`}>{attestation.eventName}</Link>
</p>

<p className="text-xs font-medium leading-6 text-gray-600">Event Role</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const AccountAbstractionController: React.FC<ScanComponentProps> = props => {
</div>

<h2 className="text-xl font-semibold">Attestations</h2>
<AccountAbstractionAttestations aaAddress={aaAddress} />
<AccountAbstractionAttestations aaAddress={aaAddress} eoaAddress={eoaAddress} />

<h2 className="text-xl font-semibold">Sign message</h2>

Expand Down
151 changes: 7 additions & 144 deletions packages/nextjs/contracts/deployedContracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { GenericContractsDeclaration } from "~~/utils/scaffold-eth/contract";
const deployedContracts = {
84531: {
Voting: {
address: "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
address: "0xB48EBD92b38dD8eC0fB2Fb49121f6e9f12BE2e34",
abi: [
{
inputs: [
Expand Down Expand Up @@ -39,6 +39,12 @@ const deployedContracts = {
name: "creator",
type: "address",
},
{
indexed: false,
internalType: "string",
name: "title",
type: "string",
},
{
indexed: false,
internalType: "bytes32",
Expand Down Expand Up @@ -206,149 +212,6 @@ const deployedContracts = {
],
inheritedFunctions: {},
},
YourContract: {
address: "0x5FbDB2315678afecb367f032d93F642f64180aa3",
abi: [
{
inputs: [
{
internalType: "address",
name: "_owner",
type: "address",
},
],
stateMutability: "nonpayable",
type: "constructor",
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "address",
name: "greetingSetter",
type: "address",
},
{
indexed: false,
internalType: "string",
name: "newGreeting",
type: "string",
},
{
indexed: false,
internalType: "bool",
name: "premium",
type: "bool",
},
{
indexed: false,
internalType: "uint256",
name: "value",
type: "uint256",
},
],
name: "GreetingChange",
type: "event",
},
{
inputs: [],
name: "greeting",
outputs: [
{
internalType: "string",
name: "",
type: "string",
},
],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "owner",
outputs: [
{
internalType: "address",
name: "",
type: "address",
},
],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "premium",
outputs: [
{
internalType: "bool",
name: "",
type: "bool",
},
],
stateMutability: "view",
type: "function",
},
{
inputs: [
{
internalType: "string",
name: "_newGreeting",
type: "string",
},
],
name: "setGreeting",
outputs: [],
stateMutability: "payable",
type: "function",
},
{
inputs: [],
name: "totalCounter",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256",
},
],
stateMutability: "view",
type: "function",
},
{
inputs: [
{
internalType: "address",
name: "",
type: "address",
},
],
name: "userGreetingCounter",
outputs: [
{
internalType: "uint256",
name: "",
type: "uint256",
},
],
stateMutability: "view",
type: "function",
},
{
inputs: [],
name: "withdraw",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
{
stateMutability: "payable",
type: "receive",
},
],
inheritedFunctions: {},
},
},
} as const;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React, { useEffect, useState } from "react";
import Link from "next/link";
import { useParams } from "next/navigation";
import { baseGoerli } from "wagmi/chains";
import deployedContracts from "~~/contracts/deployedContracts";
import { readEvents } from "~~/services/web3/polls";
import { readPollsForEvent } from "~~/services/web3/polls";

function calculateTimeLeft(timestamp: number) {
const now = new Date().getTime(); // Current timestamp in milliseconds
Expand All @@ -23,16 +25,21 @@ function calculateTimeLeft(timestamp: number) {

const Polls = () => {
const [polls, setPolls] = useState<any[]>([]);
const params = useParams();

const getEvents = async () => {
const events = (await readEvents(deployedContracts[baseGoerli.id as 84531].Voting.address)) || [];
const events =
(await readPollsForEvent(deployedContracts[baseGoerli.id as 84531].Voting.address, params.eventId as string)) ||
[];

setPolls(events.map(({ args }) => args));
setPolls(events);
};

useEffect(() => {
getEvents();
}, []);
if (params?.eventId) {
getEvents();
}
}, [params]);

const renderPolls = (poll: any, i: number) => {
const timestamp = Number(poll.endTs * 1000);
Expand All @@ -47,9 +54,9 @@ const Polls = () => {

return (
<div key={i} className="p-4 max-w-sm rounded overflow-hidden shadow-lg bg-white">
<h2 className="text-gray-700 font-bold text-xl mb-2">{poll.title || "Name"}</h2>
<h2 className="text-gray-700 font-bold text-xl mb-2">{poll.title}</h2>
<h3 className="text-gray-700 text-base">Poll ends in {`${days} days ${hours} hours ${minutes} minutes`}</h3>
<h3>{poll.pollId}</h3>
<Link href={`/user/${params.userAddress}/event/${params.eventId}/polls/${poll.id}/vote`}>Vote</Link>
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import React, { useEffect, useState } from "react";
import { useParams } from "next/navigation";
import { useContractRead } from "wagmi";
import { baseGoerli } from "wagmi/chains";
import deployedContracts from "~~/contracts/deployedContracts";
import { sendUserOperation, waitForUserOperationTransaction } from "~~/services/web3/accountAbstraction";
import { AttestationData, getAttestationsForAddress } from "~~/services/web3/attestationService";
import { getVotingUoCallData } from "~~/services/web3/voting";

const Vote = () => {
const params = useParams();
const [selectedOption, setSelectedOption] = useState<string>();
const [attestation, setAttestation] = useState<AttestationData>();

const { data } = useContractRead({
address: deployedContracts[baseGoerli.id]?.Voting.address,
abi: deployedContracts[baseGoerli.id]?.Voting.abi,
functionName: "getPoll",
args: [params?.pollId as string],
});

const handleVote = async () => {
if (attestation?.id) {
const uoCallData = getVotingUoCallData(attestation.id, params.pollId as string, Number(selectedOption));

const uo = await sendUserOperation({
signerAddress: params.userAddress as string,
to: deployedContracts[baseGoerli.id].Voting.address,
data: uoCallData,
value: BigInt(0),
});

const txHash = await waitForUserOperationTransaction(params.userAddress as string, uo.hash);

alert(txHash);
}
};

const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setSelectedOption(event.target.value);
};

const getAttestations = async () => {
const attestations = await getAttestationsForAddress("0x9513f3ECBbE3A53aa05101dDd125C5ccCa52974C");

setAttestation(attestations.find((att: { eventId: string | string[] }) => att.eventId == params?.eventId));
};

useEffect(() => {
if (params?.eventId) {
getAttestations();
}

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [params?.eventId]);

const renderOptions = () => {
return data?.options.map((option, i) => (
<div key={i} className="flex items-center mb-4">
<input type="radio" id={option.name} name="vote" value={i} className="mr-2" />
<label>{option.name}</label>
</div>
));
};

return data ? (
<div className="text-black max-w-md mx-auto mt-8 bg-white rounded-lg overflow-hidden shadow-md">
<div className="px-6 py-4">
<div className="font-bold text-xl mb-2">{data?.title}</div>
<div onChange={handleChange}>{renderOptions()}</div>
<button
disabled={!selectedOption}
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
onClick={handleVote}
>
Submit Vote
</button>
</div>
</div>
) : (
<div className="flex items-center justify-center h-screen">
<div className="border-t-8 border-blue-500 rounded-full animate-spin h-20 w-20"></div>
</div>
);
};

export default Vote;
24 changes: 22 additions & 2 deletions packages/nextjs/services/web3/polls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,32 @@ import { Contract } from "ethers";
import { baseGoerli } from "wagmi/chains";
import deployedContracts from "~~/contracts/deployedContracts";

export const readEvents = async (contractAddress: string) => {
export const readPollsForEvent = async (contractAddress: string, eventId: string) => {
const provider = await getProvider();

const abi = deployedContracts[baseGoerli.id as 84531].Voting.abi;
const fromBlock = 0;
const VotingContract = new Contract(contractAddress, abi, provider);

return await VotingContract.queryFilter("CreatePoll", fromBlock);
const allPools = await VotingContract.queryFilter("CreatePoll", fromBlock);

const withDetails = await Promise.all(
allPools.map(async event => {
const details = await VotingContract.getPoll(event.args!.id);

return {
attestationSchemaId: details.attestationSchemaId,
attester: details.attester,
endTs: details.endTs,
eventId: details.eventId,
options: details.options,
title: details.title,
id: event.args!.id,
};
}),
);

const filtered = withDetails.filter(item => item.eventId.toString() === eventId);

return filtered;
};
3 changes: 2 additions & 1 deletion packages/nextjs/services/web3/voting.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { encodeFunctionData } from "viem";
import { baseGoerli } from "wagmi/chains";
import deployedContracts from "~~/contracts/deployedContracts";

export const getVotingUoCallData = (attestationId: string, pollId: string, option: number) => {
return encodeFunctionData({
abi: deployedContracts[84531].Voting.abi,
abi: deployedContracts[baseGoerli.id as 84531]?.Voting.abi,
functionName: "vote",
args: [attestationId, pollId, BigInt(option)],
});
Expand Down

0 comments on commit a500149

Please sign in to comment.