-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Pedro Luis Frias Favero
authored and
Pedro Luis Frias Favero
committed
Jun 27, 2024
1 parent
94f3aa8
commit dff4d2f
Showing
4 changed files
with
301 additions
and
259 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,295 @@ | ||
import { Link } from "@nextui-org/link"; | ||
|
||
import { Head } from "./head"; | ||
|
||
import { Navbar } from "@/components/navbar"; | ||
|
||
import GradientBG from "@/components/GradientBG"; | ||
|
||
import { Field, PublicKey } from 'o1js'; | ||
import { useEffect, useState } from 'react'; | ||
import styles from '../styles/Home.module.css'; | ||
import '../pages/reactCOIServiceWorker'; | ||
import ZkappWorkerClient from '../pages/zkappWorkerClient'; | ||
|
||
let transactionFee = 0.1; | ||
const ZKAPP_ADDRESS = 'B62qpXPvmKDf4SaFJynPsT6DyvuxMS9H1pT4TGonDT26m599m7dS9gP'; | ||
|
||
|
||
export default function Web3Layout({ | ||
children, | ||
}: { | ||
children: React.ReactNode; | ||
}) { | ||
|
||
|
||
const [state, setState] = useState({ | ||
zkappWorkerClient: null as null | ZkappWorkerClient, | ||
hasWallet: null as null | boolean, | ||
hasBeenSetup: false, | ||
accountExists: false, | ||
currentNum: null as null | Field, | ||
publicKey: null as null | PublicKey, | ||
zkappPublicKey: null as null | PublicKey, | ||
creatingTransaction: false, | ||
}); | ||
|
||
const [displayText, setDisplayText] = useState(''); | ||
const [transactionlink, setTransactionLink] = useState(''); | ||
|
||
useEffect(() => { | ||
async function timeout(seconds: number): Promise<void> { | ||
return new Promise<void>((resolve) => { | ||
setTimeout(() => { | ||
resolve(); | ||
}, seconds * 1000); | ||
}); | ||
} | ||
|
||
(async () => { | ||
if (!state.hasBeenSetup) { | ||
setDisplayText('Loading web worker...'); | ||
console.log('Loading web worker...'); | ||
const zkappWorkerClient = new ZkappWorkerClient(); | ||
await timeout(5); | ||
|
||
setDisplayText('Done loading web worker'); | ||
console.log('Done loading web worker'); | ||
|
||
await zkappWorkerClient.setActiveInstanceToDevnet(); | ||
|
||
const mina = (window as any).mina; | ||
|
||
if (mina == null) { | ||
setState({ ...state, hasWallet: false }); | ||
return; | ||
} | ||
|
||
const publicKeyBase58: string = (await mina.requestAccounts())[0]; | ||
const publicKey = PublicKey.fromBase58(publicKeyBase58); | ||
|
||
console.log(`Using key:${publicKey.toBase58()}`); | ||
setDisplayText(`Using key:${publicKey.toBase58()}`); | ||
|
||
setDisplayText('Checking if fee payer account exists...'); | ||
console.log('Checking if fee payer account exists...'); | ||
|
||
const res = await zkappWorkerClient.fetchAccount({ | ||
publicKey: publicKey!, | ||
}); | ||
const accountExists = res.error == null; | ||
|
||
await zkappWorkerClient.loadContract(); | ||
|
||
console.log('Compiling zkApp...'); | ||
setDisplayText('Compiling zkApp...'); | ||
await zkappWorkerClient.compileContract(); | ||
console.log('zkApp compiled'); | ||
setDisplayText('zkApp compiled...'); | ||
|
||
const zkappPublicKey = PublicKey.fromBase58(ZKAPP_ADDRESS); | ||
|
||
await zkappWorkerClient.initZkappInstance(zkappPublicKey); | ||
|
||
console.log('Getting zkApp state...'); | ||
setDisplayText('Getting zkApp state...'); | ||
await zkappWorkerClient.fetchAccount({ publicKey: zkappPublicKey }); | ||
const currentNum = await zkappWorkerClient.getNum(); | ||
console.log(`Current state in zkApp: ${currentNum.toString()}`); | ||
setDisplayText(''); | ||
|
||
setState({ | ||
...state, | ||
zkappWorkerClient, | ||
hasWallet: true, | ||
hasBeenSetup: true, | ||
publicKey, | ||
zkappPublicKey, | ||
accountExists, | ||
currentNum, | ||
}); | ||
} | ||
})(); | ||
}, []); | ||
|
||
// ------------------------------------------------------- | ||
// Wait for account to exist, if it didn't | ||
|
||
useEffect(() => { | ||
(async () => { | ||
if (state.hasBeenSetup && !state.accountExists) { | ||
for (;;) { | ||
setDisplayText('Checking if fee payer account exists...'); | ||
console.log('Checking if fee payer account exists...'); | ||
const res = await state.zkappWorkerClient!.fetchAccount({ | ||
publicKey: state.publicKey!, | ||
}); | ||
const accountExists = res.error == null; | ||
if (accountExists) { | ||
break; | ||
} | ||
await new Promise((resolve) => setTimeout(resolve, 5000)); | ||
} | ||
setState({ ...state, accountExists: true }); | ||
} | ||
})(); | ||
}, [state.hasBeenSetup]); | ||
|
||
|
||
// ------------------------------------------------------- | ||
// Send a transaction | ||
|
||
const onSendTransaction = async () => { | ||
setState({ ...state, creatingTransaction: true }); | ||
|
||
setDisplayText('Creating a transaction...'); | ||
console.log('Creating a transaction...'); | ||
|
||
await state.zkappWorkerClient!.fetchAccount({ | ||
publicKey: state.publicKey!, | ||
}); | ||
|
||
await state.zkappWorkerClient!.createUpdateTransaction(); | ||
|
||
setDisplayText('Creating proof...'); | ||
console.log('Creating proof...'); | ||
await state.zkappWorkerClient!.proveUpdateTransaction(); | ||
|
||
console.log('Requesting send transaction...'); | ||
setDisplayText('Requesting send transaction...'); | ||
const transactionJSON = await state.zkappWorkerClient!.getTransactionJSON(); | ||
|
||
setDisplayText('Getting transaction JSON...'); | ||
console.log('Getting transaction JSON...'); | ||
const { hash } = await (window as any).mina.sendTransaction({ | ||
transaction: transactionJSON, | ||
feePayer: { | ||
fee: transactionFee, | ||
memo: '', | ||
}, | ||
}); | ||
|
||
const transactionLink = `https://minascan.io/devnet/tx/${hash}`; | ||
console.log(`View transaction at ${transactionLink}`); | ||
|
||
setTransactionLink(transactionLink); | ||
setDisplayText(transactionLink); | ||
|
||
setState({ ...state, creatingTransaction: false }); | ||
}; | ||
|
||
// ------------------------------------------------------- | ||
// Refresh the current state | ||
|
||
const onRefreshCurrentNum = async () => { | ||
console.log('Getting zkApp state...'); | ||
setDisplayText('Getting zkApp state...'); | ||
|
||
await state.zkappWorkerClient!.fetchAccount({ | ||
publicKey: state.zkappPublicKey!, | ||
}); | ||
const currentNum = await state.zkappWorkerClient!.getNum(); | ||
setState({ ...state, currentNum }); | ||
console.log(`Current state in zkApp: ${currentNum.toString()}`); | ||
setDisplayText(''); | ||
}; | ||
|
||
// ------------------------------------------------------- | ||
// Create UI elements | ||
|
||
let hasWallet; | ||
if (state.hasWallet != null && !state.hasWallet) { | ||
const auroLink = 'https://www.aurowallet.com/'; | ||
const auroLinkElem = ( | ||
<a href={auroLink} target="_blank" rel="noreferrer"> | ||
Install Auro wallet here | ||
</a> | ||
); | ||
hasWallet = <div>Could not find a wallet. {auroLinkElem}</div>; | ||
} | ||
|
||
const stepDisplay = transactionlink ? ( | ||
<a | ||
href={transactionlink} | ||
target="_blank" | ||
rel="noreferrer" | ||
style={{ textDecoration: 'underline' }} | ||
> | ||
View transaction | ||
</a> | ||
) : ( | ||
displayText | ||
); | ||
|
||
let setup = ( | ||
<div | ||
className={styles.start} | ||
style={{ fontWeight: 'bold', fontSize: '1.5rem', paddingBottom: '5rem' }} | ||
> | ||
{stepDisplay} | ||
{hasWallet} | ||
</div> | ||
); | ||
|
||
let accountDoesNotExist; | ||
if (state.hasBeenSetup && !state.accountExists) { | ||
const faucetLink = | ||
'https://faucet.minaprotocol.com/?address=' + state.publicKey!.toBase58(); | ||
accountDoesNotExist = ( | ||
<div> | ||
<span style={{ paddingRight: '1rem' }}>Account does not exist.</span> | ||
<a href={faucetLink} target="_blank" rel="noreferrer"> | ||
Visit the faucet to fund this fee payer account | ||
</a> | ||
</div> | ||
); | ||
} | ||
|
||
let mainContent; | ||
if (state.hasBeenSetup && state.accountExists) { | ||
mainContent = ( | ||
<div style={{ justifyContent: 'center', alignItems: 'center' }}> | ||
<div className={styles.center} style={{ padding: 0 }}> | ||
Current state in zkApp: {state.currentNum!.toString()}{' '} | ||
</div> | ||
<button | ||
className={styles.card} | ||
onClick={onSendTransaction} | ||
disabled={state.creatingTransaction} | ||
> | ||
Send Transaction | ||
</button> | ||
<button className={styles.card} onClick={onRefreshCurrentNum}> | ||
Get Latest State | ||
</button> | ||
</div> | ||
); | ||
} | ||
|
||
|
||
|
||
return ( | ||
<GradientBG> | ||
<div className="relative flex flex-col h-screen"> | ||
<Head /> | ||
<Navbar /> | ||
<main className="container mx-auto max-w-7xl px-6 flex-grow pt-16"> | ||
{setup} | ||
{accountDoesNotExist} | ||
{children} | ||
</main> | ||
<footer className="w-full flex items-center justify-center py-3"> | ||
<Link | ||
isExternal | ||
className="flex items-center gap-1 text-current" | ||
href="https://minaprotocol.com/zkapps" | ||
title="minaprotocol.com homepage" | ||
> | ||
<span className="text-default-600">Powered by</span> | ||
<p className="text-primary">Mina</p> | ||
</Link> | ||
</footer> | ||
</div> | ||
</GradientBG> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.