diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index c6e4bd4..daaaffd 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -1,371 +1,316 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-explicit-any */ "use client"; import { useState, useEffect } from "react"; import { - Box, - Card, - CardBody, - Container, - Heading, - Input, - VStack, - Text, - OrderedList, - ListItem, - useSteps, - Breadcrumb, - BreadcrumbItem, - BreadcrumbLink, - Icon, + Box, + Card, + CardBody, + Container, + Heading, + Input, + VStack, + Text, + OrderedList, + ListItem, + useSteps, + Breadcrumb, + BreadcrumbItem, + BreadcrumbLink, } from "@chakra-ui/react"; import { CheckCircleIcon, TimeIcon, WarningIcon } from "@chakra-ui/icons"; import styled from "@emotion/styled"; import axios from "axios"; declare global { - interface Window { - google: any; - } + interface Window { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + google: any; + } } const StyledListItem = styled(ListItem)` - font-family: var(--font-geist-sans); - font-size: 1rem; - line-height: 1.5; - margin-bottom: 0.5rem; - color: #4a5568; + font-family: var(--font-geist-sans); + font-size: 1rem; + line-height: 1.5; + margin-bottom: 0.5rem; + color: #4a5568; `; const StyledOrderedList = styled(OrderedList)` - padding-left: 1.5rem; - margin-bottom: 1.5rem; + padding-left: 1.5rem; + margin-bottom: 1.5rem; `; const InstructionStep = styled.span` - font-weight: 600; - color: #2b6cb0; + font-weight: 600; + color: #2b6cb0; `; -interface HomeProps { - data: string; -} - export default function Home() { - const [command, setCommand] = useState(""); - const [jwt, setJwt] = useState(""); - const [error, setError] = useState(""); - const [proof, setProof] = useState(null); - const [stepStatuses, setStepStatuses] = useState([ - "idle", - "idle", - "idle", - "idle", - ]); - const steps = [ - { title: "JWT Generation", description: "Generating JWT" }, - { title: "Proof Generation", description: "Starting proof generation" }, - { title: "Proof Complete", description: "Proof generation completed" }, - { - title: "Submit to Contract", - description: "Submitting proof to contract", - }, - ]; + const [command, setCommand] = useState(""); + const [jwt, setJwt] = useState(""); + const [error, setError] = useState(""); + const [proof, setProof] = useState(null); - const { activeStep, setActiveStep } = useSteps({ - index: 0, - count: steps.length, - }); + const [stepStatuses, setStepStatuses] = useState([ + "idle", + "idle", + "idle", + "idle", + ]); + const steps = [ + { title: "JWT Generation", description: "Generating JWT" }, + { title: "Proof Generation", description: "Starting proof generation" }, + { title: "Proof Complete", description: "Proof generation completed" }, + { + title: "Submit to Contract", + description: "Submitting proof to contract", + }, + ]; - const handleCredentialResponse = async (response: any) => { - try { - const jwt = response.credential; - console.log("JWT:", jwt); - const decodedHeader = JSON.parse( - Buffer.from( - response.credential.split(".")[0], - "base64" - ).toString("utf-8") - ); - const decodedPayload = JSON.parse( - Buffer.from( - response.credential.split(".")[1], - "base64" - ).toString("utf-8") - ); - console.log("Decoded Header:", decodedHeader); - console.log("Decoded Payload:", decodedPayload); - setJwt(jwt); - setError(""); - setStepStatuses((prev) => ["success", "idle", "idle"]); - const pubkeys = await axios.get( - "https://www.googleapis.com/oauth2/v3/certs" - ); - const pubkey = pubkeys.data.keys.find( - (key: any) => key.kid === decodedHeader.kid - ); + const handleCredentialResponse = async (response: any) => { + try { + const jwt = response.credential; + console.log("JWT:", jwt); + const decodedHeader = JSON.parse( + Buffer.from(response.credential.split(".")[0], "base64").toString( + "utf-8" + ) + ); + const decodedPayload = JSON.parse( + Buffer.from(response.credential.split(".")[1], "base64").toString( + "utf-8" + ) + ); + console.log("Decoded Header:", decodedHeader); + console.log("Decoded Payload:", decodedPayload); + setJwt(jwt); + setError(""); + setStepStatuses(() => ["success", "idle", "idle"]); + const pubkeys = await axios.get( + "https://www.googleapis.com/oauth2/v3/certs" + ); + const pubkey = pubkeys.data.keys.find( + (key: any) => key.kid === decodedHeader.kid + ); - const result = await generateProof(jwt, { - n: pubkey.n, - e: 65537, - }); - if (result) { - const { proof, pub_signals } = result; - await submitProofToContract( - proof, - pub_signals, - decodedHeader, - decodedPayload - ); - } else { - throw new Error("Failed to generate proof"); - } - } catch (error) { - console.error("Error decoding JWT:", error); - setError( - "Failed to process the sign-in response. Please try again." - ); - setStepStatuses((prev) => ["failed", "idle", "idle"]); - } - }; + const result = await generateProof(jwt, { + n: pubkey.n, + e: 65537, + }); + if (result) { + const { proof, pub_signals } = result; + await submitProofToContract( + proof, + pub_signals, + decodedHeader, + decodedPayload + ); + } else { + throw new Error("Failed to generate proof"); + } + } catch (error) { + console.error("Error decoding JWT:", error); + setError("Failed to process the sign-in response. Please try again."); + setStepStatuses(() => ["failed", "idle", "idle"]); + } + }; - useEffect(() => { - if (window.google) { - window.google.accounts.id.initialize({ - client_id: - "397234807794-fh6mhl0jppgtt0ak5cgikhlesbe8f7si.apps.googleusercontent.com", - callback: handleCredentialResponse, - }); - window.google.accounts.id.renderButton( - document.getElementById("googleSignInButton"), - { theme: "outline", size: "large" } - ); - } - }, []); + useEffect(() => { + if (window.google) { + window.google.accounts.id.initialize({ + client_id: + "397234807794-fh6mhl0jppgtt0ak5cgikhlesbe8f7si.apps.googleusercontent.com", + callback: handleCredentialResponse, + }); + window.google.accounts.id.renderButton( + document.getElementById("googleSignInButton"), + { theme: "outline", size: "large" } + ); + } + }, []); - useEffect(() => { - if (window.google) { - window.google.accounts.id.cancel(); - if (command) { - window.google.accounts.id.initialize({ - client_id: - "397234807794-fh6mhl0jppgtt0ak5cgikhlesbe8f7si.apps.googleusercontent.com", - callback: handleCredentialResponse, - nonce: command, - }); - window.google.accounts.id.renderButton( - document.getElementById("googleSignInButton"), - { theme: "outline", size: "large" } - ); - } - } - }, [command]); + useEffect(() => { + if (window.google) { + window.google.accounts.id.cancel(); + if (command) { + window.google.accounts.id.initialize({ + client_id: + "397234807794-fh6mhl0jppgtt0ak5cgikhlesbe8f7si.apps.googleusercontent.com", + callback: handleCredentialResponse, + nonce: command, + }); + window.google.accounts.id.renderButton( + document.getElementById("googleSignInButton"), + { theme: "outline", size: "large" } + ); + } + } + }, [command]); - const generateProof = async (jwt: string, pubkey: any) => { - try { - setStepStatuses((prev) => [ - "success", - "processing", - "idle", - "idle", - ]); - const circuitInputs = await axios.post( - "/api/generateCircuitInputs", - { - jwt, - pubkey, - maxMessageLength: 1024, - } - ); - const proverResponse = await axios.post("/api/proxyJwtProver", { - input: circuitInputs.data, - }); - setProof(proverResponse.data.proof); - setStepStatuses((prev) => [ - "success", - "success", - "success", - "idle", - ]); + const generateProof = async (jwt: string, pubkey: any) => { + try { + setStepStatuses(() => ["success", "processing", "idle", "idle"]); + const circuitInputs = await axios.post("/api/generateCircuitInputs", { + jwt, + pubkey, + maxMessageLength: 1024, + }); + const proverResponse = await axios.post("/api/proxyJwtProver", { + input: circuitInputs.data, + }); + setProof(proverResponse.data.proof); + setStepStatuses(() => ["success", "success", "success", "idle"]); - return { - proof: proverResponse.data.proof, - pub_signals: proverResponse.data.pub_signals, - }; - } catch (error) { - console.error("Error generating proof:", error); - if (axios.isAxiosError(error) && error.response) { - setError( - `Failed to generate proof: ${error.response.data.message || error.message}` - ); - } else { - setError("Failed to generate proof. Please try again."); - } - setStepStatuses((prev) => ["success", "failed", "idle", "idle"]); - } - }; + return { + proof: proverResponse.data.proof, + pub_signals: proverResponse.data.pub_signals, + }; + } catch (error) { + console.error("Error generating proof:", error); + if (axios.isAxiosError(error) && error.response) { + setError( + `Failed to generate proof: ${error.response.data.message || error.message}` + ); + } else { + setError("Failed to generate proof. Please try again."); + } + setStepStatuses(() => ["success", "failed", "idle", "idle"]); + } + }; - const submitProofToContract = async ( - proof: any, - pub_signals: any, - header: any, - payload: any - ) => { - try { - setStepStatuses((prev) => [ - "success", - "success", - "success", - "processing", - ]); - console.log("Submitting proof to contract:", proof, pub_signals); - const response = await axios.post("/api/submitProofToContract", { - proof, - pub_signals, - header, - payload, - }); - console.log("Proof submitted to contract:", response.data); - setStepStatuses((prev) => [ - "success", - "success", - "success", - "success", - ]); - } catch (error) { - console.error("Error submitting proof to contract:", error); - if (axios.isAxiosError(error) && error.response) { - setError( - `Failed to submit proof: ${error.response.data.message || error.message}` - ); - } else { - setError( - "Failed to submit proof to contract. Please try again." - ); - } - setStepStatuses((prev) => [ - "success", - "success", - "success", - "failed", - ]); - } - }; + const submitProofToContract = async ( + proof: any, + pub_signals: any, + header: any, + payload: any + ) => { + try { + setStepStatuses(() => ["success", "success", "success", "processing"]); + console.log("Submitting proof to contract:", proof, pub_signals); + const response = await axios.post("/api/submitProofToContract", { + proof, + pub_signals, + header, + payload, + }); + console.log("Proof submitted to contract:", response.data); + setStepStatuses(() => ["success", "success", "success", "success"]); + } catch (error) { + console.error("Error submitting proof to contract:", error); + if (axios.isAxiosError(error) && error.response) { + setError( + `Failed to submit proof: ${error.response.data.message || error.message}` + ); + } else { + setError("Failed to submit proof to contract. Please try again."); + } + setStepStatuses(() => ["success", "success", "success", "failed"]); + } + }; - const renderBreadcrumb = () => ( - - {steps.map((step, index) => ( - - - {stepStatuses[index] === "success" && ( - - )} - {stepStatuses[index] === "processing" && ( - - )} - {stepStatuses[index] === "failed" && ( - - )} - {stepStatuses[index] === "idle" && ( - - )} - {step.title} - - - ))} - - ); + const renderBreadcrumb = () => ( + + {steps.map((step, index) => ( + + + {stepStatuses[index] === "success" && } + {stepStatuses[index] === "processing" && } + {stepStatuses[index] === "failed" && } + {stepStatuses[index] === "idle" && ( + + )} + {step.title} + + + ))} + + ); - return ( - - - - JWT-Wallet - - - - - - Welcome to JWT-Wallet! Follow these steps to get - started: - - - - - Enter a command - {" "} - in the input field below (e.g., "Send 0.12 - ETH to 0x1234...") - - - The{" "} - - Google Sign-In button - {" "} - will become active once you've entered a - command - - - - Click the Google Sign-In button - {" "} - to authenticate and generate a JWT - - - - Check the console - {" "} - for the decoded JWT information - - - setCommand(e.target.value)} - size="lg" - borderColor="blue.300" - _hover={{ borderColor: "blue.400" }} - _focus={{ - borderColor: "blue.500", - boxShadow: "0 0 0 1px #3182ce", - }} - fontFamily="var(--font-geist-mono)" - /> - - {renderBreadcrumb()} - - - - - - ); + return ( + + + + JWT-Wallet + + + + + + Welcome to JWT-Wallet! Follow these steps to get started: + + + + Enter a command in the + input field below (e.g., "Send 0.12 ETH to + 0x1234...") + + + The Google Sign-In button{" "} + will become active once you've entered a command + + + + Click the Google Sign-In button + {" "} + to authenticate and generate a JWT + + + Check the console for the + decoded JWT information + + + setCommand(e.target.value)} + size="lg" + borderColor="blue.300" + _hover={{ borderColor: "blue.400" }} + _focus={{ + borderColor: "blue.500", + boxShadow: "0 0 0 1px #3182ce", + }} + fontFamily="var(--font-geist-mono)" + /> + + {renderBreadcrumb()} + + + + + + ); } diff --git a/frontend/pages/api/proxyJwtProver.ts b/frontend/pages/api/proxyJwtProver.ts index 53a6f97..38735be 100644 --- a/frontend/pages/api/proxyJwtProver.ts +++ b/frontend/pages/api/proxyJwtProver.ts @@ -1,5 +1,5 @@ import type { NextApiRequest, NextApiResponse } from "next"; -import axios, { AxiosError } from "axios"; +import axios from "axios"; export default async function handler( req: NextApiRequest, diff --git a/frontend/pages/api/submitProofToContract.ts b/frontend/pages/api/submitProofToContract.ts index 239880f..e97a035 100644 --- a/frontend/pages/api/submitProofToContract.ts +++ b/frontend/pages/api/submitProofToContract.ts @@ -5,7 +5,7 @@ import { sepolia } from "viem/chains"; import { config } from "dotenv"; import { encodeAbiParameters, parseAbiParameters } from "viem"; -const contractABI = require("../../public/JwtVerifier.json").abi; +import { abi as contractABI } from "../../public/JwtVerifier.json"; const contractAddress = "0x63E990e29317Bf54a6c4F5Fb26e33342D3DE6Fd3"; config();