Integrate account salt endpoint

Update relayer class.
Update react component flows.
This commit is contained in:
jacque006
2024-04-07 14:16:15 -04:00
parent df7cbe70f1
commit c8809b0a28
4 changed files with 75 additions and 49 deletions

View File

@@ -4,10 +4,11 @@ import { abi as safeAbi } from '../abi/Safe.json'
import { abi as recoveryPluginAbi } from '../abi/SafeZkEmailRecoveryPlugin.json'
import { safeZkSafeZkEmailRecoveryPlugin } from '../../contracts.base-sepolia.json'
import { Button } from './Button'
import { genAccountCode, getGuardianSalt, getRequestGuardianSubject } from '../utils/email'
import { genAccountCode, getRequestGuardianSubject, templateIdx } from '../utils/email'
import { readContract } from 'wagmi/actions'
import { config } from '../providers/config'
import { pad } from 'viem'
import { relayer } from '../services/relayer'
export function ConfigureSafeModule() {
const { address } = useAccount()
@@ -66,14 +67,13 @@ export function ConfigureSafeModule() {
}
const accountCode = await genAccountCode();
const guardianSalt = await getGuardianSalt(guardianEmail, accountCode);
const guardianSalt = await relayer.getAccountSalt(accountCode, guardianEmail);
const guardianAddr = await readContract(config, {
abi: recoveryPluginAbi,
address: safeZkSafeZkEmailRecoveryPlugin as `0x${string}`,
functionName: 'computeEmailAuthAddress',
args: [guardianSalt]
})
const subject = getRequestGuardianSubject(address);
// TODO Should this be something else?
const previousOwnerInLinkedList = pad("0x1", {
size: 20
@@ -93,16 +93,23 @@ export function ConfigureSafeModule() {
console.debug('recovery configured');
accountCode;
subject;
const recoveryRelayerAddr = await readContract(config, {
abi: recoveryPluginAbi,
address: safeZkSafeZkEmailRecoveryPlugin as `0x${string}`,
functionName: 'getRouterForSafe',
args: [address]
}) as string;
// const { requestId } = await relayer.acceptanceRequest(
// emailRecoveryRelayer,
// guardianEmail,
// accountCode,
// templateIdx,
// subject,
// );
const subject = getRequestGuardianSubject(address);
const { requestId } = await relayer.acceptanceRequest(
recoveryRelayerAddr,
guardianEmail,
accountCode,
templateIdx,
subject,
);
console.debug('req guard req id', requestId)
setRecoveryConfigured(true);
}, [

View File

@@ -12,7 +12,12 @@ import {
simpleWalletImpl
} from '../../contracts.base-sepolia.json'
import { ethers } from 'ethers'
import { genAccountCode, getRequestGuardianSubject, getRequestsRecoverySubject } from '../utils/email'
import {
genAccountCode,
getRequestGuardianSubject,
getRequestsRecoverySubject,
templateIdx
} from '../utils/email'
// TODO Pull from lib
type HexStr = `0x${string}`;
@@ -23,8 +28,6 @@ const storageKeys = {
accountCode: 'accountCode',
}
const templateIdx = 0
// TODO Switch back to Safe over SimpleWallet
export function PerformRecovery() {
const cfg = useConfig()

View File

@@ -24,9 +24,8 @@ class Relayer {
}
async requestStatus(requestId: number) {
// TODO type res body
const { data } = await axios({
method: 'GET',
method: 'POST',
url: `${this.apiUrl}/requestStatus`,
data: {
request_id: requestId
@@ -88,6 +87,18 @@ class Relayer {
})
return data;
}
async getAccountSalt(accountCode: string, emailAddress: string) {
const { data } = await axios<unknown, { data: string }>({
method: "POST",
url: `${this.apiUrl}/getAccountSalt`,
data: {
account_code: accountCode,
email_addr: emailAddress,
}
})
return data
}
}
export const relayer = new Relayer(import.meta.env.VITE_RELAYER_URL);

View File

@@ -1,25 +1,27 @@
import { buildPoseidon, Poseidon } from "circomlibjs";
import { buildPoseidon } from "circomlibjs";
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 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;
}
// 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]
@@ -28,22 +30,25 @@ export function bytesToHex(bytes: Uint8Array) {
.join("");
}
export async function genAccountCode(): Promise<Uint8Array> {
export async function genAccountCode(): Promise<string> {
const poseidon = await buildPoseidon();
const accountCodeBytes: Uint8Array = poseidon.F.random();
return accountCodeBytes;
return bytesToHex(accountCodeBytes);
}
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;
}
// 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 subject
export const getRequestGuardianSubject = (acctAddr: string) => `Accept guardian request for ${acctAddr}`;
export const getRequestsRecoverySubject = (acctAddr: string, newOwner: string) => `Set the new signer of ${acctAddr} to ${newOwner}`;
export const getRequestGuardianSubject = (acctAddr: string) =>
`Accept guardian request for ${acctAddr}`;
export const getRequestsRecoverySubject = (acctAddr: string, newOwner: string) =>
`Set the new signer of ${acctAddr} to ${newOwner}`;