diff --git a/src/components/GuardianSetup.tsx b/src/components/GuardianSetup.tsx index 6dbc89c..1e1c0ea 100644 --- a/src/components/GuardianSetup.tsx +++ b/src/components/GuardianSetup.tsx @@ -9,7 +9,6 @@ import { useAppContext } from "../context/AppContextHook"; import { safeEmailRecoveryModule } from "../../contracts.base-sepolia.json"; import { genAccountCode, - getRequestGuardianCommand, templateIdx, } from "../utils/email"; import { readContract } from "wagmi/actions"; @@ -190,8 +189,6 @@ const GuardianSetup = () => { console.debug("recovery configured"); - // const command = getRequestGuardianCommand(address); - const command = await readContract(config, { abi: safeEmailRecoveryModuleAbi, address: safeEmailRecoveryModule as `0x${string}`, diff --git a/src/components/PerformRecovery.tsx b/src/components/PerformRecovery.tsx deleted file mode 100644 index 2b2708c..0000000 --- a/src/components/PerformRecovery.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { useState, useCallback } from 'react' -import { Button } from './Button' -import { relayer } from '../services/relayer' -import { abi as recoveryPluginAbi } from '../abi/SafeEmailRecoveryModule' -import { useReadContract, useAccount } from 'wagmi' -import { - getRequestsRecoveryCommand, - templateIdx -} from '../utils/email' -import { safeEmailRecoveryModule } from '../../contracts.base-sepolia.json' -import { useAppContext } from '../context/AppContextHook' - -export function PerformRecovery() { - const { address } = useAccount() - - const { guardianEmail } = useAppContext() - - const [newOwner, setNewOwner] = useState() - - // TODO pull from recovery module - // const { data: timelock } = useReadContract({ - // address: simpleWalletAddress as HexStr, - // abi: simpleWalletAbi, - // functionName: 'timelock', - // }); - - const { data: recoveryRouterAddr } = useReadContract({ - abi: recoveryPluginAbi, - address: safeEmailRecoveryModule as `0x${string}`, - functionName: 'getRouterForSafe', - args: [address] - }); - - const requestRecovery = useCallback(async () => { - if (!address) { - throw new Error('unable to get account address'); - } - - if (!guardianEmail) { - throw new Error('guardian email not set') - } - - if (!newOwner) { - throw new Error('new owner not set') - } - - if (!recoveryRouterAddr) { - throw new Error('could not find recovery router for safe') - } - - const command = getRequestsRecoveryCommand(address, newOwner) - - const { requestId } = await relayer.recoveryRequest( - recoveryRouterAddr as string, - guardianEmail, - templateIdx, - command, - ) - console.debug('recovery request id', requestId) - - }, [recoveryRouterAddr, address, guardianEmail, newOwner]) - - const completeRecovery = useCallback(async () => { - if (!recoveryRouterAddr) { - throw new Error('could not find recovery router for safe') - } - - console.debug('recovery router addr', recoveryRouterAddr); - const res = relayer.completeRecovery( - recoveryRouterAddr as string - ); - - console.debug('complete recovery res', res) - }, [recoveryRouterAddr]); - - return ( - <> - - - - {/*
{`TEST timelock: ${timelock}`}
*/} - - - ); -} diff --git a/src/components/RequestedRecoveries.tsx b/src/components/RequestedRecoveries.tsx index eec2621..078400f 100644 --- a/src/components/RequestedRecoveries.tsx +++ b/src/components/RequestedRecoveries.tsx @@ -7,7 +7,7 @@ import { useReadContract } from "wagmi"; import infoIcon from "../assets/infoIcon.svg"; import { relayer } from "../services/relayer"; -import { getRequestsRecoveryCommand, getRequestsRecoveryCommandForSafe13, templateIdx } from "../utils/email"; +import { templateIdx } from "../utils/email"; import { safeEmailRecoveryModule } from "../../contracts.base-sepolia.json"; import { StepsContext } from "../App"; import toast from "react-hot-toast"; diff --git a/src/components/burnerWallet/GuardianSetup.tsx b/src/components/burnerWallet/GuardianSetup.tsx index 1d0bb04..3d10a39 100644 --- a/src/components/burnerWallet/GuardianSetup.tsx +++ b/src/components/burnerWallet/GuardianSetup.tsx @@ -1,17 +1,12 @@ -import { useCallback, useContext, useEffect, useMemo, useState } from "react"; -import { ConnectKitButton } from "connectkit"; +import { useCallback, useContext, useEffect, useState } from "react"; import { Button } from "../Button"; -import { useAccount, useReadContract, useWriteContract } from "wagmi"; +import { useWriteContract } from "wagmi"; import infoIcon from "../../assets/infoIcon.svg"; import { useAppContext } from "../../context/AppContextHook"; import { abi as universalEmailRecoveryModuleAbi } from "../../abi/UniversalEmailRecoveryModule.json"; import { universalEmailRecoveryModule } from "../../../contracts.base-sepolia.json"; -import { - genAccountCode, - getRequestGuardianCommand, - templateIdx, -} from "../../utils/email"; +import { genAccountCode, templateIdx } from "../../utils/email"; import { readContract } from "wagmi/actions"; import { config } from "../../providers/config"; import { relayer } from "../../services/relayer"; @@ -41,8 +36,6 @@ import { TextField, Typography, } from "@mui/material"; -import { useTheme } from "@mui/material"; -import Loader from "../Loader"; import { useGetSafeAccountAddress } from "../../utils/useGetSafeAccountAddress"; const TIME_UNITS = { @@ -77,14 +70,11 @@ const isValidEmail = (email: string) => { const GuardianSetup = () => { const address = useGetSafeAccountAddress(); const { writeContractAsync } = useWriteContract(); - const [account, setAccount] = useState(null); - const [accountCreationError, setAccountCreationError] = useState(false); const { guardianEmail, setGuardianEmail, accountCode, setAccountCode } = useAppContext(); const stepsContext = useContext(StepsContext); - const [isAccountInitialized, setIsAccountInitialized] = useState(false); const [isAccountInitializedLoading, setIsAccountInitializedLoading] = useState(false); const [loading, setLoading] = useState(false); @@ -109,8 +99,6 @@ const GuardianSetup = () => { let interval: NodeJS.Timeout; - const isMobile = window.innerWidth < 768; - const checkIfRecoveryIsConfigured = async () => { if (!address) { return; @@ -125,7 +113,6 @@ const GuardianSetup = () => { console.log(getGuardianConfig); - // TODO: add polling for this if ( getGuardianConfig.acceptedWeight === getGuardianConfig.threshold && getGuardianConfig.threshold !== 0n @@ -173,10 +160,6 @@ const GuardianSetup = () => { const acctCode = await genAccountCode(); - // if (localStorage.getItem("accountCode")) { - // return; - // } - localStorage.setItem("accountCode", acctCode); await setAccountCode(accountCode); @@ -193,7 +176,6 @@ const GuardianSetup = () => { }); const burnerWalletAddress = await run(client, safeAccount, guardianAddr); - setAccount(burnerWalletAddress); localStorage.setItem( "burnerWalletConfig", JSON.stringify({ burnerWalletAddress }) @@ -202,7 +184,6 @@ const GuardianSetup = () => { } catch (error) { console.log(error); toast.error(`Something went wrong. Err: ${error.shortMessage}`); - setAccountCreationError(error); } finally { setIsBurnerWalletCreating(false); } @@ -239,25 +220,34 @@ const GuardianSetup = () => { throw new Error("guardian email not set"); } + if(!localStorageAccountCode) { + toast.error("Seomthing went wrong, please restart the flow") + console.error("Invalid account code") + } + try { setLoading(true); - toast( - "Please check your email", - { - icon: , - style: { - background: "white", - }, - } - ); + toast("Please check your email", { + icon: , + style: { + background: "white", + }, + }); + + const subject = await readContract(config, { + abi: universalEmailRecoveryModuleAbi, + address: universalEmailRecoveryModule as `0x${string}`, + functionName: "acceptanceCommandTemplates", + args: [], + }); + console.log(subject, "command"); - const subject = getRequestGuardianCommand(address); const { requestId } = await relayer.acceptanceRequest( universalEmailRecoveryModule as `0x${string}`, guardianEmail, localStorageAccountCode, templateIdx, - subject + subject[0].join().replaceAll(",", " ").replace("{ethAddr}", address) ); // Setting up interval for polling @@ -265,7 +255,7 @@ const GuardianSetup = () => { checkIfRecoveryIsConfigured(); }, 5000); // Adjust the interval time (in milliseconds) as needed } catch (err) { - console.log(err); + console.error(err); toast.error( err?.shortMessage ?? "Something went wrong, please try again." ); @@ -350,38 +340,6 @@ const GuardianSetup = () => { - - {/* - Recovery Expiry (hours) - - setRecoveryExpiry( - parseInt((e.target as HTMLInputElement).value) - ) - } - title='Recovery Expiry (hours)' - message='This is the expiry delay that...' - /> - */} - - {/* - Connected Wallet: - - */} @@ -421,7 +379,7 @@ const GuardianSetup = () => { > {isWalletPresent ? ( ) : ( - ) : null} - - ); -}; - -export default SafeModuleRecovery; diff --git a/src/utils/burnerWalletUtils.ts b/src/utils/burnerWalletUtils.ts index 16bbd77..1f79e04 100644 --- a/src/utils/burnerWalletUtils.ts +++ b/src/utils/burnerWalletUtils.ts @@ -3,8 +3,6 @@ import { createWalletClient, custom, parseEther, - encodePacked, - encodeFunctionData, encodeAbiParameters, toFunctionSelector, } from "viem"; @@ -20,14 +18,11 @@ import { import { walletClientToSmartAccountSigner } from "permissionless/utils"; import { createPublicClient, http } from "viem"; import { baseSepolia } from "viem/chains"; -import { installModule, erc7579Actions } from "permissionless/actions/erc7579"; -import { abi as safeAbi } from "../abi/Safe"; +import { erc7579Actions } from "permissionless/actions/erc7579"; import { abi as safeEmailRecoveryModuleAbi } from "../abi/EmailRecoveryManager.json"; import { readContract } from "wagmi/actions"; import { genAccountCode, - getRequestGuardianCommand, - templateIdx, } from "../utils/email"; import { relayer } from "../services/relayer"; import { config } from "../providers/config"; diff --git a/src/utils/email.ts b/src/utils/email.ts index b80b091..8e0fc33 100644 --- a/src/utils/email.ts +++ b/src/utils/email.ts @@ -1,32 +1,7 @@ import { buildPoseidon } from "circomlibjs"; -import { - safeEmailRecoveryModule, - universalEmailRecoveryModule, -} from "../../contracts.base-sepolia.json"; export const templateIdx = 0; -// From https://github.com/zkemail/email-wallet/blob/main/packages/frontend/src/components/RegisterUnclaim.tsx -// function padStringToBytes(str: string, len: number): Uint8Array { -// const bytes = new Uint8Array(len); -// const strBytes = (new TextEncoder).encode(str); -// bytes.set(strBytes); -// const empty = new Uint8Array(len - strBytes.length); -// bytes.set(empty, strBytes.length); -// return bytes; -// } - -// function bytes2fields(bytes: Uint8Array, F: Poseidon['F']): bigint[] { -// const fields: bigint[] = []; -// for (let i = 0; i < bytes.length; i += 31) { -// const bytes32 = new Uint8Array(32); -// bytes32.set(bytes.slice(i, i + 31)); -// const val = F.fromRprLE(bytes32, 0); -// fields.push(val); -// } -// return fields; -// } - export function bytesToHex(bytes: Uint8Array) { return [...bytes] .reverse() @@ -39,47 +14,3 @@ export async function genAccountCode(): Promise { const accountCodeBytes: Uint8Array = poseidon.F.random(); return bytesToHex(accountCodeBytes); } - -// Use relayer.getAccountSalt instead -// export async function getGuardianSalt(guardianEmail: string, accountCode: Uint8Array) { -// const poseidon = await buildPoseidon(); -// const emailField = bytes2fields(padStringToBytes(guardianEmail, 256), poseidon.F); -// const accountSaltBytes = poseidon([ -// ...emailField, accountCode, 0 -// ]); -// const accountSalt: `0x${string}` = `0x${bytesToHex(accountSaltBytes)}` -// return accountSalt; -// } - -// TODO Update both with safe module accept command -export const getRequestGuardianCommand = (acctAddr: string) => - `Accept guardian request for ${acctAddr}`; - -export const getRequestsRecoveryCommandForSafe13 = ( - userAccountAddr: string, - acctAddr: string, - newOwner: string -) => - `Recover account ${acctAddr} from old owner ${userAccountAddr} to new owner ${newOwner}`; - - -export const getRequestsRecoveryCommand = ( - userAccountAddr: string, - acctAddr: string, - newOwner: string -) => - // TODO: Retrieve the command from the recovery module contract - `Recover account ${acctAddr} from old owner ${userAccountAddr} to new owner ${newOwner} using recovery module ${safeEmailRecoveryModule}`; - -export const getRequestsRecoverySubjectForBurnerWallet = ( - userAccountAddr: string, - acctAddr: string, - newOwner: string -) => - // `Update owner to ${newOwner} on account ${acctAddr}`; - `Recover account ${acctAddr} from old owner ${userAccountAddr} to new owner ${newOwner}`; - -export const getRequestsRecoveryCommandForBurnerWallet = ( - acctAddr: string, - recoveryDataHash: string -) => `Recover account ${acctAddr} using recovery hash ${recoveryDataHash}`;