Skip to content

Commit

Permalink
Merge pull request #2 from zama-ai/update-bundle
Browse files Browse the repository at this point in the history
fix: update bundle
  • Loading branch information
immortal-tofu authored Dec 16, 2024
2 parents 150e5b5 + c6171d0 commit 36790f3
Show file tree
Hide file tree
Showing 12 changed files with 490 additions and 534 deletions.
25 changes: 25 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Test

on:
pull_request:
branches:
- main
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [20.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run prettier:check
- run: npm run build
56 changes: 23 additions & 33 deletions app/components/Connect/Connect.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
'use client';

import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { BrowserProvider } from 'ethers';

import './Connect.css';
import { Eip1193Provider } from 'ethers';
import { createFhevmInstance } from '../../fhevmjs';

declare var window: any

const AUTHORIZED_CHAIN_ID = ['0x1f49', '0x1f4a', '0x1f4b', '0x2328'];
const AUTHORIZED_CHAIN_ID = ['0xaa36a7', '0x2328'];

export const Connect: React.FC<{
children: (account: string, provider: any) => React.ReactNode;
Expand All @@ -17,21 +17,29 @@ export const Connect: React.FC<{
const [account, setAccount] = useState<string>('');
const [error, setError] = useState<string | null>(null);
const [provider, setProvider] = useState<BrowserProvider | null>(null);
const [loading, setLoading] = useState(true);

const refreshAccounts = (accounts: string[]) => {
setAccount(accounts[0] || '');
setConnected(accounts.length > 0);
};

const hasValidNetwork = async (): Promise<boolean> => {
const currentChainId: string = await window.ethereum.request({ method: 'eth_chainId' });
const currentChainId: string = await window.ethereum.request({
method: 'eth_chainId',
});
return AUTHORIZED_CHAIN_ID.includes(currentChainId.toLowerCase());
};

const refreshNetwork = useCallback(async () => {
if (await hasValidNetwork()) {
await createFhevmInstance();
setValidNetwork(true);
setLoading(true);
const load = async () => {
await createFhevmInstance();
setLoading(false);
};
window.requestAnimationFrame(load);
} else {
setValidNetwork(false);
}
Expand Down Expand Up @@ -62,7 +70,7 @@ export const Connect: React.FC<{
});
eth.on('accountsChanged', refreshAccounts);
eth.on('chainChanged', refreshNetwork);
}, [refreshNetwork]);
}, []);

const connect = async () => {
if (!provider) {
Expand All @@ -86,25 +94,9 @@ export const Connect: React.FC<{
params: [{ chainId: AUTHORIZED_CHAIN_ID[0] }],
});
} catch (e) {
await window.ethereum.request({
method: 'wallet_addEthereumChain',
params: [
{
chainId: AUTHORIZED_CHAIN_ID[0],
rpcUrls: ['https://devnet.zama.ai/'],
chainName: 'Zama Devnet',
nativeCurrency: {
name: 'ZAMA',
symbol: 'ZAMA',
decimals: 18,
},
blockExplorerUrls: ['https://main.explorer.zama.ai'],
},
],
});
console.error('No Sepolia chain configured');
}
await refreshNetwork();
}, [refreshNetwork]);
}, []);

const child = useMemo<React.ReactNode>(() => {
if (!account || !provider) {
Expand All @@ -116,28 +108,26 @@ export const Connect: React.FC<{
<div>
<p>You&apos;re not on the correct network</p>
<p>
<button className="Connect__button" onClick={switchNetwork}>
Switch to Zama Devnet
</button>
<button onClick={switchNetwork}>Switch to Sepolia</button>
</p>
</div>
);
}

if (loading) {
return <p>Loading...</p>;
}

return children(account, provider);
}, [account, provider, validNetwork, children, switchNetwork]);
}, [account, provider, children, validNetwork, loading]);

if (error) {
return <p>No wallet has been found.</p>;
}

const connectInfos = (
<div className="Connect__info">
{!connected && (
<button className="Connect__button" onClick={connect}>
Connect your wallet
</button>
)}
{!connected && <button onClick={connect}>Connect your wallet</button>}
{connected && <div className="Connect__account">Connected with {account}</div>}
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion app/components/Connect/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './Connect';
export * from "./Connect";
63 changes: 35 additions & 28 deletions app/components/Devnet/Devnet.tsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,58 @@
import { useEffect, useState } from "react";
import { getInstance } from "../../fhevmjs";
'use client';

import "./Devnet.css";
import { useEffect, useState } from 'react';
import { getInstance } from '../../fhevmjs';
import './Devnet.css';
import { Eip1193Provider } from 'ethers';

const toHexString = (bytes: Uint8Array) =>
bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
const toHexString = (bytes: Uint8Array) => bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '');

export const Devnet = () => {
export type DevnetProps = {
account: string;
provider: Eip1193Provider;
};

const CONTRACT_ADDRESS = '0x309cf2aae85ad8a1db70ca88cfd4225bf17a7482';

export const Devnet = ({ account }: DevnetProps) => {
const [handles, setHandles] = useState<Uint8Array[]>([]);
const [encryption, setEncryption] = useState<Uint8Array>();
const [eip712, setEip712] =
useState<ReturnType<typeof instance.createEIP712>>();
const [eip712, setEip712] = useState<ReturnType<typeof instance.createEIP712>>();
const instance = getInstance();

// Handle EIP712 setup
useEffect(() => {
const { handles, inputProof } = instance
.createEncryptedInput(
"0x309cf2aae85ad8a1db70ca88cfd4225bf17a7456",
"0x309cf2aae85ad8a1db70ca88cfd4225bf17a7482"
)
.add64(32)
.encrypt();
setHandles(handles);
setEncryption(inputProof);
const { publicKey } = instance.generateKeypair();
const eip = instance.createEIP712(
publicKey,
"0x309cf2aae85ad8a1db70ca88cfd4225bf17a7482"
);
const eip = instance.createEIP712(publicKey, CONTRACT_ADDRESS);
setEip712(eip);
}, [instance]);

const encrypt = async (val: number) => {
const now = Date.now();
try {
const result = await instance.createEncryptedInput(CONTRACT_ADDRESS, account).add64(val).encrypt();

console.log(`Took ${(Date.now() - now) / 1000}s`);
setHandles(result.handles);
setEncryption(result.inputProof);
} catch (e) {
console.error('Encryption error:', e);
console.log(Date.now() - now);
}
};

return (
<div>
<dl>
<button onClick={() => encrypt(1337)}>Encrypt 1337</button>
<dt className="Devnet__title">This is an encryption of 1337:</dt>
<dd className="Devnet__dd">
<pre className="Devnet__pre">
Handle: {handles.length && toHexString(handles[0])}
</pre>
<pre className="Devnet__pre">
Input Proof: {encryption && toHexString(encryption)}
</pre>
<pre className="Devnet__pre">Handle: {handles.length ? toHexString(handles[0]) : ''}</pre>
<pre className="Devnet__pre">Input Proof: {encryption ? toHexString(encryption) : ''}</pre>
</dd>
<dt className="Devnet__title">And this is a EIP-712 token</dt>
<dd className="Devnet__dd">
<pre className="Devnet__pre">{eip712 && JSON.stringify(eip712)}</pre>
<pre className="Devnet__pre">{eip712 ? JSON.stringify(eip712) : ''}</pre>
</dd>
</dl>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/components/Devnet/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './Devnet';
export * from "./Devnet";
18 changes: 13 additions & 5 deletions app/fhevmjs.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { isAddress } from "ethers";
import { initFhevm, createInstance, FhevmInstance } from "fhevmjs";
import { initFhevm, createInstance, FhevmInstance } from "fhevmjs/bundle";

const ACL_ADDRESS: string = "0x9479B455904dCccCf8Bc4f7dF8e9A1105cBa2A8e";

export type Keypair = {
publicKey: string;
Expand All @@ -14,7 +16,7 @@ type Keypairs = {
};

export const init = async () => {
await initFhevm();
await initFhevm({ thread: navigator.hardwareConcurrency });
};

let instancePromise: Promise<FhevmInstance>;
Expand All @@ -24,22 +26,28 @@ const keypairs: Keypairs = {};

export const createFhevmInstance = async () => {
if (instancePromise) return instancePromise;
instancePromise = createInstance({ network: window.ethereum });

instancePromise = createInstance({
network: window.ethereum,
aclContractAddress: ACL_ADDRESS,
kmsContractAddress: "0x904Af2B61068f686838bD6257E385C2cE7a09195",
gatewayUrl: "https://gateway.sepolia.zama.ai/",
});
instance = await instancePromise;
};

export const setKeypair = (
contractAddress: string,
userAddress: string,
keypair: Keypair
keypair: Keypair,
) => {
if (!isAddress(contractAddress) || !isAddress(userAddress)) return;
keypairs[userAddress][contractAddress] = keypair;
};

export const getKeypair = (
contractAddress: string,
userAddress: string
userAddress: string,
): Keypair | null => {
if (!isAddress(contractAddress) || !isAddress(userAddress)) return null;
return keypairs[userAddress]
Expand Down
9 changes: 9 additions & 0 deletions app/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/// <reference types="vite/client" />

interface Window {
ethereum: import("ethers").Eip1193Provider & {
on: (event: string, cb: (param: any) => any) => void;
};
fhevmjs: import("fhevmjs");
fhevmjsInitialized: boolean;
}
29 changes: 16 additions & 13 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'
import './index.css'
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import './globals.css';
import './index.css';
import Script from 'next/script';

const inter = Inter({ subsets: ['latin'] })
const inter = Inter({ subsets: ['latin'] });

export const metadata: Metadata = {
title: 'fhEVM Next App',
description: 'Template for using fhevmjs in NextJS',
}
};

export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<head>
<title>lol</title>
<Script src="https://cdn.zama.ai/fhevmjs/0.6.2/fhevmjs.umd.cjs" strategy="beforeInteractive" />
</head>
<body className={inter.className}>
<div id="root">{children}</div>
</body>
</html>
)
);
}
17 changes: 11 additions & 6 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

'use client'
'use client';

import { useEffect, useState } from 'react';
import { Devnet } from './components/Devnet';
Expand All @@ -10,23 +9,29 @@ function App() {
const [isInitialized, setIsInitialized] = useState(false);

useEffect(() => {
// Trick to avoid double init with HMR
if (window.fhevmjsInitialized) return;
window.fhevmjsInitialized = true;
init()
.then(() => {
setIsInitialized(true);
})
.catch(() => setIsInitialized(false));
.catch((e) => {
console.log(e);
setIsInitialized(false);
});
}, []);

if (!isInitialized) return null;

return (
<div id="root">
<>
<h1>fhevmjs</h1>
<Connect>{(account, provider) => <Devnet />}</Connect>
<Connect>{(account, provider) => <Devnet account={account} provider={provider} />}</Connect>
<p className="read-the-docs">
<a href="https://docs.zama.ai/fhevm">See the documentation for more information</a>
</p>
</div>
</>
);
}

Expand Down
Loading

0 comments on commit 36790f3

Please sign in to comment.