Skip to content
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

Move proof generation to frontend #23

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
58 changes: 0 additions & 58 deletions webApp/components/Form.tsx

This file was deleted.

95 changes: 95 additions & 0 deletions webApp/components/ProofGenerator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import React from "react";
import Router from "next/router";
import styles from "../styles/Home.module.css";

export default function ProofGenerator() {
const inputRef = React.useRef(null);
const [loading, setLoading] = React.useState(false);
const [downloading, setDownloading] = React.useState(true);
let [leaves, setLeaves] = React.useState([] as string[]);

// Get the merkle leaves
React.useEffect(() => {
fetch("leaves.txt")
.then((r) => r.text())
.then((text) => {
let leaves = text.split(",");
setLeaves(leaves);
});
}, []);

const checkAndGenerateProof = async (address: string) => {
setLoading(true);
try {
// const pipeline = promisify(stream.pipeline);
// const { filename } = req.query;

// Download the file from the server
// const url = `leaves.txt`;
// const fileRes = await fetch(url);

// if (!fileRes.ok) {
// throw new Error(`unexpected response ${fileRes.statusText}`);
// }

// console.log("File downloaded: ", fileRes);
// if (fileRes.body === null) {
// throw new Error(`File body is null`);
// }
// let leaves = fileRes.body.toString().split(",");

while (leaves.length === 0) {
console.log("Waiting for leaves to load");
await new Promise((resolve) => setTimeout(resolve, 10));
console.log("Waiting for leaves to load");
}
console.log("Loaded file: ", leaves.length, " addresses.");
if (!leaves.includes(address)) {
throw new Error(`Address not found in merkle tree`);
}

console.log("Leaves loaded, starting proof generation");

const response = await fetch("/api/claim", {
method: "POST",
body: JSON.stringify({
address: (inputRef.current as any)?.value,
}),
});
const resJson = await response.json();
console.log(resJson);
if (resJson.error) {
throw new Error(resJson.error);
}
Router.push("/Claimed");
} catch (e) {
console.error(e);
Router.push("/Declined");
} finally {
setLoading(false);
}
};

return (
<div>
<div className={styles.description2}>Claim with address:</div>
<div className={styles.loading}>
{loading && <div>Loading ... (it might take a minute)</div>}
</div>
<div className={styles.inputContainer}>
<label>address: </label>
<input type="text" id="address" name="address" ref={inputRef} />
<button
className={styles.formButton}
type="submit"
disabled={loading || (inputRef.current as any)?.value === ""}
onClick={() =>
checkAndGenerateProof((inputRef.current as any)?.value)
}
>
Claim
</button>
</div>
</div>
);
}
4 changes: 2 additions & 2 deletions webApp/pages/Claimed_Before.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import styles from "../styles/Home.module.css";
import React from "react";
import Form from "../components/Form";
import ProofGenerator from "../components/ProofGenerator";
import type { NextPage } from "next";
// import Router, { useRouter } from "next/router";

Expand All @@ -18,7 +18,7 @@ const Home: NextPage = () => {
<br />
<br />
<br />
<Form />
<ProofGenerator />
</main>
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions webApp/pages/Declined.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import styles from "../styles/Home.module.css";
import React from "react";
import Form from "../components/Form";
import ProofGenerator from "../components/ProofGenerator";
import type { NextPage } from "next";
// import Router, { useRouter } from "next/router";

Expand All @@ -19,7 +19,7 @@ const Home: NextPage = () => {
<br />
<br />
<br />
<Form />
<ProofGenerator />
</main>
</div>
);
Expand Down
23 changes: 21 additions & 2 deletions webApp/pages/api/claim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from "defender-relay-client/lib/ethers";
import MerkleTree from "merkletreejs";
import keccak256 from "keccak256";
import { existsSync, readFileSync } from "fs";
import { readdir, readFileSync } from "fs";
import CollectorAbi from "../../abi/Collector.json";
import { MerkleProof } from "../../components/MerkleProof";

Expand Down Expand Up @@ -79,15 +79,34 @@ export default function handler(

console.log("fullPath: ", fullPath);

console.log("process.cwd(): ", process.cwd());
console.log("files in current directory:");
readdir(process.cwd(), (err, files) => {
files.forEach((file) => {
console.log(file);
});
});

console.log("files in private directory:");
readdir(path.join(process.cwd(), "private"), (err, files) => {
files.forEach((file) => {
console.log(file);
});
});

let addressesArray = readFileSync(fullPath).toString().split(",");
console.log("Loaded file: ", addressesArray.length, " addresses.");
if (!addressesArray.includes(address)) {
return res
.status(400)
.json({ data: `${address} is not in the merkle tree` });
}

console.log("Address found in array.");
// generate merkle proof
let [proof, root] = generateMerkleProof(address, addressesArray);
console.log("Merkle proof generated.");
console.log("proof: ", proof);
console.log("root: ", root);

// create signer
let provider: providers.Provider;
Expand Down
117 changes: 66 additions & 51 deletions webApp/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { ConnectButton } from "@rainbow-me/rainbowkit";
import React, { useState, useEffect } from "react";
import type { NextPage } from "next";
import Image from 'next/image'
import Link from "next/link"
import Image from "next/image";
import Link from "next/link";
import Router, { useRouter } from "next/router";
import Head from "next/head";
import Form from '../components/Form';
import ProofGenerator from "../components/ProofGenerator";
import styles from "../styles/Home.module.css";
import { MerkleProof } from "../components/MerkleProof";

Expand Down Expand Up @@ -56,70 +56,85 @@ const Home: NextPage = () => {
/>
<link href="/favicon.ico" rel="icon" />
</Head>

<main className={styles.main}>
<h1 className={styles.title}>GOERLINATOR</h1>
<h2 className={styles.description}>terminating your GoerliETH shortage</h2>
<h2 className={styles.description}>
terminating your GoerliETH shortage
</h2>
<Image
src="/goerlinator_talking.png"
alt="Goerlinator"
width={600}
height={300}
src="/goerlinator_talking.png"
alt="Goerlinator"
width={600}
height={300}
/>
{/* <ConnectButton /> */}
<div className={styles.box}>
Addresses that had at least one POAP before March 1, 2023 are eligible for a one-time 50 GoerliETH claim.
Addresses that had at least one POAP before March 1, 2023 are eligible
for a one-time 50 GoerliETH claim.
</div>
<div className={styles.flexBox}>
<Form />
<ProofGenerator />
</div>
</main>

<footer className={styles.footer}>
<div
style={{
display: "flex",
justifyContent: "center",
}}
>
<Link href="https://github.com/malteish/goerlinator">
<a>
<Image
src="/github-logo-white.png"
alt="github-logo"
width="50"
height="50"
/>
</a>
</Link>
</div>
<div className={styles.container}>
GoerliETH funded by: <a href="https://twitter.com/MPtherealmvp" rel="noopener noreferrer" target="_blank">Maria Paula
</a>
<br />
Project created by: <a
href="https://twitter.com/malteish"
rel="noopener noreferrer"
target="_blank">Malteish
</a>
&
<a
href="https://twitter.com/MacBudkowski"
rel="noopener noreferrer"
target="_blank">Mac
</a>
<br />
Inspired by: <a
href="https://grabteeth.xyz/"
rel="noopener noreferrer"
target="_blank">grabteeth
</a>
<div
style={{
display: "flex",
justifyContent: "center",
}}
>
<Link href="https://github.com/malteish/goerlinator">
<a>
<Image
src="/github-logo-white.png"
alt="github-logo"
width="50"
height="50"
/>
</a>
</Link>
</div>
<div className={styles.container}>
GoerliETH funded by:{" "}
<a
href="https://twitter.com/MPtherealmvp"
rel="noopener noreferrer"
target="_blank"
>
Maria Paula
</a>
<br />
Project created by:{" "}
<a
href="https://twitter.com/malteish"
rel="noopener noreferrer"
target="_blank"
>
Malteish
</a>
&
<a
href="https://twitter.com/MacBudkowski"
rel="noopener noreferrer"
target="_blank"
>
Mac
</a>
<br />
Inspired by:{" "}
<a
href="https://grabteeth.xyz/"
rel="noopener noreferrer"
target="_blank"
>
grabteeth
</a>
</div>
</footer>
</div>
);
};



export default Home;
File renamed without changes.