Skip to content

Commit

Permalink
WIP: Add logic to add/remove guardians
Browse files Browse the repository at this point in the history
  • Loading branch information
wryonik committed Sep 26, 2024
1 parent d666815 commit 84c46d7
Showing 1 changed file with 193 additions and 57 deletions.
250 changes: 193 additions & 57 deletions src/components/ConfigureGuardians.tsx
Original file line number Diff line number Diff line change
@@ -1,123 +1,259 @@
import {
Box,
Dialog,
DialogContent,
DialogTitle,
Grid,
Typography,
} from "@mui/material";
import { useContext, useState } from "react";
import { readContract } from "wagmi/actions";
import toast from "react-hot-toast";
import { useAccount, useReadContract, useWriteContract } from "wagmi";
import { readContract } from "wagmi/actions";
import { Button } from "./Button";
import InputField from "./InputField";
import { safeEmailRecoveryModule } from "../../contracts.base-sepolia.json";
import { safeAbi } from "../abi/Safe";
import { safeEmailRecoveryModuleAbi } from "../abi/SafeEmailRecoveryModule";
import { StepsContext } from "../App";
import { STEPS } from "../constants";
import { config } from "../providers/config";
import { relayer } from "../services/relayer";
import { Box, Grid, Typography } from "@mui/material";
import toast from "react-hot-toast";
import { STEPS } from "../constants";
import { StepsContext } from "../App";

const AddGuardianModal = ({
open,
handleClose,
newGuardianAddress,
setNewGuardianAddress,
newGuardianEmail,
setNewGuardianEmail,
handleAddGuardian,
isAddGuardianLoading,
}: {
open: boolean;
handleClose: () => void;
newGuardianAddress: string;
setNewGuardianAddress: (address: string) => void;
newGuardianEmail: string;
setNewGuardianEmail: (email: string) => void;
handleAddGuardian: () => void;
isAddGuardianLoading: boolean;
}) => {
return (
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="parent-dialog-title"
aria-describedby="parent-dialog-description"
PaperProps={{
style: {
borderRadius: "16px",
width: "40rem",
},
}}
>
<DialogTitle id="parent-dialog-title" style={{ fontWeight: "bold" }}>
Add Guardian
</DialogTitle>
<DialogContent>
<Grid container spacing={2}>
<Grid item xs={12}>
<InputField
type="string"
value={newGuardianAddress || ""}
onChange={(e) => setNewGuardianAddress(e.target.value)}
label="Guardian Address"
/>
</Grid>
<Grid item xs={12}>
<InputField
type="email"
value={newGuardianEmail || ""}
onChange={(e) => setNewGuardianEmail(e.target.value)}
label="Guardian Email"
/>
</Grid>
<Grid item xs={6}>
<Button onClick={handleClose} disabled={isAddGuardianLoading}>
Cancel
</Button>
</Grid>
<Grid item xs={6}>
<Button
onClick={handleAddGuardian}
disabled={isAddGuardianLoading}
loading={isAddGuardianLoading}
filled={true}
>
Add Guardian
</Button>
</Grid>
</Grid>
</DialogContent>
</Dialog>
);
};

const ConfigureGuardians = () => {
const isMobile = window.innerWidth < 768;

const { address } = useAccount();
const { writeContractAsync } = useWriteContract();
const stepsContext = useContext(StepsContext);
const accountCode = localStorage.getItem("safe1_3AccountCode");

const [newGuardianAddress, setNewGuardianAddress] = useState("");
const [newGuardianEmail, setNewGuardianEmail] = useState("");
const accountCode = localStorage.getItem("safe1_3AccountCode");
const [isAddGuardianLoading, setIsAddGuardianLoading] = useState(false);
const [isAddGuardianModalOpen, setIsAddGuardianModalOpen] = useState(false);

const { data: safeOwnersData } = useReadContract({
address,
abi: safeAbi,
functionName: "getOwners",
});

const getGuardianConfig = async () => {
const getGuardianConfig = await readContract(config, {

Check failure on line 117 in src/components/ConfigureGuardians.tsx

View workflow job for this annotation

GitHub Actions / eslint

'getGuardianConfig' is assigned a value but never used
abi: safeEmailRecoveryModuleAbi,
address: safeEmailRecoveryModule as `0x${string}`,
functionName: "getGuardianConfig",
args: [address as `0x${string}`],
});
};

getGuardianConfig();

if (!accountCode) {
toast.error("Something went wrong");
stepsContext?.setStep(STEPS.CONFIGURE_GUARDIANS);
}

console.log(safeOwnersData, "safeOwnersData");

const handleAddGuardian = async () => {
setIsAddGuardianLoading(true);
// The account code is unique for each account.

const guardianSalt = await relayer.getAccountSalt(
accountCode,
newGuardianEmail
);

console.log(newGuardianAddress, guardianSalt);

const guardianAddr = await readContract(config, {
abi: safeEmailRecoveryModuleAbi,
address: safeEmailRecoveryModule as `0x${string}`,
functionName: "computeEmailAuthAddress",
args: [newGuardianAddress, guardianSalt],
});

console.log(guardianAddr, "guardianAddr");
const res = await writeContractAsync({
abi: safeEmailRecoveryModuleAbi,
address: safeEmailRecoveryModule as `0x${string}`,
functionName: "addGuardian",
args: [guardianAddr, 1n],
});
try {
await writeContractAsync({
abi: safeEmailRecoveryModuleAbi,
address: safeEmailRecoveryModule as `0x${string}`,
functionName: "addGuardian",
args: [guardianAddr, 1n],
});

console.log(res);
setIsAddGuardianModalOpen(false);
toast.success("Guardian added successfully");
} catch (err) {
toast.error(`Something went wrong: ${err}`);
console.log(err);
} finally {
setIsAddGuardianLoading(false);
}
};

const handleRemoveGuardian = async (address: `0x${string}`) => {
// TODO: get guardian email address
const guardianSalt = await relayer.getAccountSalt(
accountCode,
newGuardianEmail
);

const guardianAddr = await readContract(config, {
abi: safeEmailRecoveryModuleAbi,
address: safeEmailRecoveryModule as `0x${string}`,
functionName: "computeEmailAuthAddress",
args: [address, guardianSalt],
});

await writeContractAsync({
abi: safeEmailRecoveryModuleAbi,
address: safeEmailRecoveryModule as `0x${string}`,
functionName: "removeGuardian",
args: [address],
args: [guardianAddr],
});
};

const handleEditGuardian = async (address: `0x${string}`) => {
handleRemoveGuardian(address);
handleAddGuardian();
};

return (
<div className="connect-wallets-container">
<Box sx={{ marginX: "auto", marginTop: "150px" }}>
<Box
sx={{
marginX: "auto",
marginTop: { xs: "2rem", sm: "9.375rem" },
marginBottom: "6.25rem",
maxWidth: isMobile ? "100%" : "50%",
}}
>
<Typography variant="h2" sx={{ paddingBottom: "20px" }}>
Configure Guardians
</Typography>
<Typography variant="h5">Current guardians:</Typography>
{safeOwnersData?.map((safeOwnerAddress) => (
<Grid container alignItems={"center"}>
<Grid item xs={8}>
<Typography>{safeOwnerAddress}</Typography>
<Grid container spacing={4}>
<Grid
container
item
justifyContent={"space-between"}
alignItems={"center"}
>
<Grid item>
<Typography variant="h5">Current guardians:</Typography>
</Grid>
<Grid item xs={4} container spacing={2}>
<Grid item>
<Button onClick={() => handleEditGuardian(safeOwnerAddress)}>
Edit
</Button>
</Grid>
<Grid item>
<Button onClick={() => handleRemoveGuardian(safeOwnerAddress)}>
Remove
</Button>
</Grid>
<Grid item>
<Button
onClick={() => setIsAddGuardianModalOpen(true)}
filled={true}
>
+ Add Guardian
</Button>
</Grid>
</Grid>
))}
{/* each one of these will have 2 buttons, edit and remove. Edit button will remove and add a new guardian at the same time */}
Add guardian: input field
<InputField
type="string"
value={newGuardianAddress || ""}
onChange={(e) => setNewGuardianAddress(e.target.value)}
label="Guardian Address"
/>
<InputField
type="email"
value={newGuardianEmail || ""}
onChange={(e) => setNewGuardianEmail(e.target.value)}
label="Guardian Email"
<Grid container item spacing={2}>
{/* TODO: Update guardian addresses */}
{[
safeOwnersData,
"0xA22a81d92F78A24dD023A868DD93a09FCEa326c3",
"0x70839221d17e106711DCfeC3f9bAEd4285bC9011",
]?.map((safeOwnerAddress) => (
<Grid
container
item
alignItems={"center"}
justifyContent={"space-between"}
direction={"row"}
>
<Grid item>
<Typography>{safeOwnerAddress}</Typography>
</Grid>
<Grid item>
<Button
onClick={() => handleRemoveGuardian(safeOwnerAddress)}
>
Remove
</Button>
</Grid>
</Grid>
))}
</Grid>
</Grid>
<AddGuardianModal
open={isAddGuardianModalOpen}
handleClose={() => setIsAddGuardianModalOpen(false)}
newGuardianAddress={newGuardianAddress}
setNewGuardianAddress={setNewGuardianAddress}
newGuardianEmail={newGuardianEmail}
setNewGuardianEmail={setNewGuardianEmail}
handleAddGuardian={handleAddGuardian}
isAddGuardianLoading={isAddGuardianLoading}
/>
<Button onClick={() => handleAddGuardian()}>Add Guardian</Button>
</Box>
</div>
);
Expand Down

0 comments on commit 84c46d7

Please sign in to comment.