Skip to content

Commit

Permalink
feat: use eip712 typed structured data signing
Browse files Browse the repository at this point in the history
  • Loading branch information
jaybuidl committed Oct 3, 2023
1 parent d4eb2da commit 889cef7
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 18 deletions.
18 changes: 8 additions & 10 deletions web/netlify/functions/update-settings.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Handler } from "@netlify/functions";
import { verifyMessage } from "viem";
import { verifyTypedData } from "viem";
import { createClient } from "@supabase/supabase-js";
import { arbitrumGoerli } from "viem/chains";
import messages from "../../src/consts/eip712-messages";

const SUPABASE_KEY = process.env.SUPABASE_CLIENT_API_KEY;
const SUPABASE_URL = process.env.SUPABASE_URL;
Expand All @@ -12,17 +12,15 @@ export const handler: Handler = async (event) => {
if (!event.body) {
throw new Error("No body provided");
}
// TODO: sanitize the body
// TODO: sanitize event.body
const { email, telegram, nonce, address, signature } = JSON.parse(event.body);
const lowerCaseAddress = address.toLowerCase() as `0x${string}`;
const data = {
address: lowerCaseAddress,
message: `Email:${email},Nonce:${nonce}`,
signature,
};
// Note: this does NOT work for smart contract wallets, but viem's publicClient.verifyMessage() fails to verify atm.
// https://viem.sh/docs/utilities/verifyMessage.html
const isValid = await verifyMessage(data);
// https://viem.sh/docs/utilities/verifyTypedData.html
const isValid = await verifyTypedData({
...messages.contactDetails(address, nonce, telegram, email),
signature,
});
if (!isValid) {
// If the recovered address does not match the provided address, return an error
throw new Error("Signature verification failed");
Expand Down
24 changes: 24 additions & 0 deletions web/src/consts/eip712-messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export default {
contactDetails: (address: `0x${string}`, nonce, telegram = "", email = "") =>
({
address: address.toLowerCase() as `0x${string}`,
domain: {
name: "Kleros v2",
version: "1",
chainId: 421_613,
},
types: {
ContactDetails: [
{ name: "email", type: "string" },
{ name: "telegram", type: "string" },
{ name: "nonce", type: "string" },
],
},
primaryType: "ContactDetails",
message: {
email,
telegram,
nonce,
},
} as const),
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useWalletClient, useAccount } from "wagmi";
import { Button } from "@kleros/ui-components-library";
import { uploadSettingsToSupabase } from "utils/uploadSettingsToSupabase";
import FormContact from "./FormContact";
import messages from "../../../../../../../consts/eip712-messages";

const FormContainer = styled.form`
position: relative;
Expand Down Expand Up @@ -36,14 +37,15 @@ const FormNotifs: React.FC = () => {

const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!address) {
throw new Error("Missing address");
}
const nonce = new Date().getTime().toString();
const signature = await walletClient?.signMessage({
account: address,
message: `Email:${emailInput},Nonce:${nonce}`,
});
if (!address || !signature) {
console.error("Missing address or signature");
return;
const signature = await walletClient?.signTypedData(
messages.contactDetails(address, nonce, telegramInput, emailInput)
);
if (!signature) {
throw new Error("Missing signature");
}
const data = {
email: emailInput,
Expand Down Expand Up @@ -80,7 +82,7 @@ const FormNotifs: React.FC = () => {
</FormContactContainer>

<ButtonContainer>
<Button text="Save" disabled={!emailIsValid} />
<Button text="Save" disabled={!emailIsValid && !telegramIsValid} />
</ButtonContainer>
</FormContainer>
);
Expand Down

0 comments on commit 889cef7

Please sign in to comment.