Skip to content

Commit

Permalink
add interactivity to nextjs starter project
Browse files Browse the repository at this point in the history
  • Loading branch information
hattyhattington17 committed Dec 2, 2024
1 parent 15a2110 commit 3cfa82a
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 17 deletions.
108 changes: 91 additions & 17 deletions src/lib/ui/next/customNextPage.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,96 @@
export default `'use client';
import Head from 'next/head';
import Image from 'next/image';
import { useEffect } from 'react';
import {useCallback, useEffect, useRef, useState} from 'react';
import GradientBG from '../components/GradientBG.js';
import styles from '../styles/Home.module.css';
import heroMinaLogo from '../public/assets/hero-mina-logo.svg';
import arrowRightSmall from '../public/assets/arrow-right-small.svg';
import './reactCOIServiceWorker';
import {fetchAccount, Mina, PublicKey} from "o1js";
import {Add} from "../../contracts";
// We've already deployed the Add contract on testnet at this address
// https://minascan.io/devnet/account/B62qnTDEeYtBHBePA4yhCt4TCgDtA4L2CGvK7PirbJyX4pKH8bmtWe5
const zkAppAddress = "B62qnTDEeYtBHBePA4yhCt4TCgDtA4L2CGvK7PirbJyX4pKH8bmtWe5";
export default function Home() {
const zkApp = useRef<Add>(new Add(PublicKey.fromBase58(zkAppAddress)));
const [transactionLink, setTransactionLink] = useState<string | null>(null);
const [contractState, setContractState] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState<boolean>(true);
// fetch the zkapp state when the page loads
useEffect(() => {
(async () => {
const { Mina, PublicKey } = await import('o1js');
const { Add } = await import('../../contracts/build/src/');
Mina.setActiveInstance(Mina.Network('https://api.minascan.io/node/devnet/v1/graphql'));
await fetchAccount({publicKey: zkAppAddress});
const num = zkApp.current.num.get();
setContractState(num.toString());
setLoading(false);
})();
}, []);
const updateZkApp = useCallback(async () => {
setTransactionLink(null);
setLoading(true);
try {
// Retrieve Mina provider injected by browser extension wallet
const mina = (window as any).mina;
const walletKey: string = (await mina.requestAccounts())[0];
console.log("Connected wallet address: " + walletKey);
await fetchAccount({publicKey: PublicKey.fromBase58(walletKey)});
// Update this to use the address (public key) for your zkApp account.
// To try it out, you can try this address for an example "Add" smart contract that we've deployed to
// Testnet B62qnTDEeYtBHBePA4yhCt4TCgDtA4L2CGvK7PirbJyX4pKH8bmtWe5.
const zkAppAddress = '';
// This should be removed once the zkAppAddress is updated.
if (!zkAppAddress) {
console.error(
'The following error is caused because the zkAppAddress has an empty string as the public key. Update the zkAppAddress with the public key for your zkApp account, or try this address for an example "Add" smart contract that we deployed to Testnet: B62qnTDEeYtBHBePA4yhCt4TCgDtA4L2CGvK7PirbJyX4pKH8bmtWe5'
);
// Compile the contract so that o1js has the proving key required to execute contract calls
console.log("Compiling Add contract to generate proving and verification keys");
await Add.compile();
// Execute a transaction locally on the browser
const transaction = await Mina.transaction(async () => {
console.log("Executing Add.update() locally");
await zkApp.current.update();
});
// Prove execution of the contract using the proving key
console.log("Proving execution of Add.update()");
await transaction.prove();
// Broadcast the transaction to the Mina network
console.log("Broadcasting proof of execution to the Mina network");
const {hash} = await mina.sendTransaction({transaction: transaction.toJSON()});
// display the link to the transaction
const transactionLink = "https://minascan.io/devnet/tx/" + hash;
setTransactionLink(transactionLink);
} catch (e: any) {
console.error(e.message);
let errorMessage = "";
if (e.message.includes("Cannot read properties of undefined (reading 'requestAccounts')")) {
errorMessage = "Is Auro installed?";
} else if (e.message.includes("Please create or restore wallet first.")) {
errorMessage = "Have you created a wallet?";
} else if (e.message.includes("User rejected the request.")) {
errorMessage = "Did you grant the app permission to connect to your wallet?";
} else {
errorMessage = "An unknown error occurred.";
}
//const zkApp = new Add(PublicKey.fromBase58(zkAppAddress))
})();
setError(errorMessage);
} finally {
setLoading(false);
}
}, []);
return (
<>
<Head>
<title>Mina zkApp UI</title>
<meta name="description" content="built with o1js" />
<link rel="icon" href="/assets/favicon.ico" />
<meta name="description" content="built with o1js"/>
<link rel="icon" href="/assets/favicon.ico"/>
</Head>
<GradientBG>
<main className={styles.main}>
Expand Down Expand Up @@ -60,6 +118,22 @@ export default function Home() {
Get started by editing
<code className={styles.code}> app/page.tsx</code>
</p>
<div className={styles.state}>
{error ? (
<span className={styles.error}>Error: {error}</span>
) : (
<div>
<div>Contract State: <span className={styles.bold}>{contractState}</span></div>
{loading ?
<div>Loading...</div> :
(transactionLink ?
<a href={transactionLink} className={styles.bold} target="_blank" rel="noopener noreferrer">
View Transaction on MinaScan
</a> :
<button onClick={updateZkApp} className={styles.button}>Call Add.update()</button>)}
</div>
)}
</div>
<div className={styles.grid}>
<a
href="https://docs.minaprotocol.com/zkapps"
Expand Down Expand Up @@ -147,4 +221,4 @@ export default function Home() {
</>
);
}
`;
`;
31 changes: 31 additions & 0 deletions src/lib/ui/next/styles/Home.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,37 @@
justify-items: center;
}

.state button {
display: block;
margin: .5rem auto 1rem;
background-color: rgb(255, 255, 255);
border: 1px solid #2d2d2d;
padding: .25rem .5rem;
cursor: pointer;
}
.state button:hover {
background-color: lightgray;
}

.state {
padding: 0.8rem 1rem;
gap: 0.5rem;
margin: 1rem;
background-color: rgb(255, 255, 255);
border: 1px solid #2d2d2d;
width: 14rem;
height: 6rem;
text-align: center;
}

.state .error {
color: red;
}

.state .bold {
font-family: var(--font-monument-bold);
}

.card {
padding: 0.8rem 1rem;
gap: 0.5rem;
Expand Down

0 comments on commit 3cfa82a

Please sign in to comment.