Skip to content

Commit

Permalink
feat: add integration to confirm recovery view
Browse files Browse the repository at this point in the history
  • Loading branch information
MiniRoman authored and aon committed Feb 4, 2025
1 parent 8224b10 commit 8fe79b7
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 28 deletions.
43 changes: 43 additions & 0 deletions packages/auth-server/composables/useRecoveryGuardian.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,29 @@ export const useRecoveryGuardian = () => {
}
}

const getRecoveryInProgress = ref(false);
const getRecoveryError = ref<Error | null>(null);

async function getRecovery(account: Address) {
getRecoveryInProgress.value = true;
getRecoveryError.value = null;

try {
const client = getPublicClient({ chainId: defaultChain.id });
return await client.readContract({
address: contractsByChain[defaultChain.id].recovery,
abi: GuardianRecoveryModuleAbi,
functionName: "pendingRecoveryData",
args: [account],
});
} catch (err) {
getRecoveryError.value = err as Error;
return [];
} finally {
getRecoveryInProgress.value = false;
}
}

const { inProgress: proposeGuardianInProgress, error: proposeGuardianError, execute: proposeGuardian } = useAsync(async (address: Address) => {
const client = getClient({ chainId: defaultChain.id });
const tx = await client.proposeGuardian({
Expand Down Expand Up @@ -91,6 +114,20 @@ export const useRecoveryGuardian = () => {
return tx;
});

const { inProgress: initRecoveryInProgress, error: initRecoveryError, execute: initRecovery } = useAsync(async (account: Address, passKey: `0x${string}`, accountId: string) => {
const client = await getWalletClient({ chainId: defaultChain.id });
const [address] = await client.getAddresses();

const tx = await client.writeContract({
account: address,
address: contractsByChain[defaultChain.id].recovery,
abi: GuardianRecoveryModuleAbi,
functionName: "initRecovery",
args: [account, passKey, accountId],
});
return tx;
});

return {
confirmGuardianInProgress,
confirmGuardianError,
Expand All @@ -101,12 +138,18 @@ export const useRecoveryGuardian = () => {
removeGuardianInProgress,
removeGuardianError,
removeGuardian,
initRecoveryInProgress,
initRecoveryError,
initRecovery,
getGuardedAccountsInProgress,
getGuardedAccountsError,
getGuardedAccounts,
getGuardiansInProgress,
getGuardiansError,
getGuardiansData,
getGuardians,
getRecoveryInProgress,
getRecoveryError,
getRecovery,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@
v-if="accountData.isConnected && !isSuccess"
class="w-full lg:w-fit"
:disabled="!isAccountGuardian"
@click="handleSuccess"
:loading="initRecoveryInProgress"
@click="confirmRecoveryAction"
>
Sign Recovery Transaction
</ZkButton>
Expand Down Expand Up @@ -132,13 +133,16 @@
<script setup lang="ts">
import { CheckCircleIcon, ExclamationTriangleIcon } from "@heroicons/vue/24/solid";
import { useAppKitAccount } from "@reown/appkit/vue";
import { hexToBytes, isAddressEqual, zeroAddress } from "viem";
import { encodePasskeyModuleParameters, getPublicKeyBytesFromPasskeySignature } from "zksync-sso/utils";
import { z } from "zod";
import { uint8ArrayToHex } from "@/utils/formatters";
import { AddressSchema } from "@/utils/schemas";
const error = ref<string | null>(null);
const accountData = useAppKitAccount();
const { getRecovery, initRecovery, initRecoveryInProgress, getGuardians, getGuardiansData } = useRecoveryGuardian();
definePageMeta({
layout: "dashboard",
Expand Down Expand Up @@ -167,6 +171,8 @@ const RecoveryParamsSchema = z
);
const recoveryParams = ref<z.infer<typeof RecoveryParamsSchema> | null>(null);
const isAccountGuardian = ref(false);
const isSuccess = ref(false);
try {
recoveryParams.value = await RecoveryParamsSchema.parseAsync({
Expand All @@ -175,14 +181,37 @@ try {
credentialPublicKey: route.query.credentialPublicKey,
checksum: route.query.checksum,
});
await getGuardians(recoveryParams.value.accountAddress);
const recoveryStatus = await getRecovery(recoveryParams.value.accountAddress);
isSuccess.value = recoveryStatus[2] === route.query.credentialId;
} catch {
error.value = "Invalid recovery parameters. Please verify the URL and try again.";
}
const isAccountGuardian = ref(true);
const isSuccess = ref(false);
watchEffect(() => {
isAccountGuardian.value = !!(getGuardiansData.value?.find((x) => isAddressEqual(x.addr, (accountData.value.address as `0x${string}`) ?? zeroAddress))?.isReady);
});
const handleSuccess = () => {
const confirmRecoveryAction = async () => {
let origin: string | undefined = undefined;
if (!origin) {
try {
origin = window.location.origin;
} catch {
throw new Error("Can't identify expectedOrigin, please provide it manually");
}
}
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
const passkeyPublicKey = getPublicKeyBytesFromPasskeySignature(hexToBytes(`0x${recoveryParams.value?.credentialPublicKey!}`));
const encodedPasskeyParameters = encodePasskeyModuleParameters({
passkeyPublicKey,
expectedOrigin: origin,
});
const accountId = recoveryParams.value?.credentialId || encodedPasskeyParameters;
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
await initRecovery(recoveryParams.value?.accountAddress!, encodedPasskeyParameters, accountId);
isSuccess.value = true;
};
</script>
124 changes: 101 additions & 23 deletions packages/sdk/src/abi/GuardianRecoveryModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@ export const GuardianRecoveryModuleAbi = [
{
inputs: [
{
internalType: "address",
internalType: "contract WebAuthValidator",
name: "_webAuthValidator",
type: "address",
},
{
internalType: "contract AAFactory",
name: "_aaFactory",
type: "address",
},
],
stateMutability: "nonpayable",
type: "constructor",
},
{
inputs: [],
name: "CooldownPerionNotPassed",
name: "CooldownPeriodNotPassed",
type: "error",
},
{
Expand Down Expand Up @@ -79,6 +84,19 @@ export const GuardianRecoveryModuleAbi = [
name: "RecoveryInitiated",
type: "event",
},
{
inputs: [],
name: "aaFactory",
outputs: [
{
internalType: "contract AAFactory",
name: "",
type: "address",
},
],
stateMutability: "view",
type: "function",
},
{
inputs: [
{
Expand All @@ -104,6 +122,11 @@ export const GuardianRecoveryModuleAbi = [
name: "isReady",
type: "bool",
},
{
internalType: "uint64",
name: "addedAt",
type: "uint64",
},
],
stateMutability: "view",
type: "function",
Expand All @@ -128,10 +151,32 @@ export const GuardianRecoveryModuleAbi = [
type: "function",
},
{
inputs: [],
name: "disable",
outputs: [],
stateMutability: "nonpayable",
inputs: [
{
internalType: "string",
name: "accountId",
type: "string",
},
],
name: "checkRecoveryRequest",
outputs: [
{
internalType: "address",
name: "account",
type: "address",
},
{
internalType: "bool",
name: "ready",
type: "bool",
},
{
internalType: "uint256",
name: "remainingTime",
type: "uint256",
},
],
stateMutability: "view",
type: "function",
},
{
Expand Down Expand Up @@ -206,6 +251,11 @@ export const GuardianRecoveryModuleAbi = [
name: "isReady",
type: "bool",
},
{
internalType: "uint64",
name: "addedAt",
type: "uint64",
},
],
internalType: "struct GuardianRecoveryValidator.Guardian[]",
name: "",
Expand All @@ -217,44 +267,67 @@ export const GuardianRecoveryModuleAbi = [
},
{
inputs: [
{
internalType: "address",
name: "accountToRecover",
type: "address",
},
{
internalType: "bytes",
name: "initData",
name: "passkey",
type: "bytes",
},
{
internalType: "string",
name: "accountId",
type: "string",
},
],
name: "init",
name: "initRecovery",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
{
inputs: [
{
internalType: "address",
name: "accountToRecover",
internalType: "contract WebAuthValidator",
name: "_webAuthValidator",
type: "address",
},
{
internalType: "contract AAFactory",
name: "_aaFactory",
type: "address",
},
],
name: "initialize",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
{
inputs: [
{
internalType: "bytes",
name: "passkey",
name: "",
type: "bytes",
},
],
name: "initRecovery",
name: "onInstall",
outputs: [],
stateMutability: "nonpayable",
type: "function",
},
{
inputs: [
{
internalType: "address",
name: "_webAuthValidator",
type: "address",
internalType: "bytes",
name: "",
type: "bytes",
},
],
name: "initialize",
name: "onUninstall",
outputs: [],
stateMutability: "nonpayable",
type: "function",
Expand All @@ -279,6 +352,11 @@ export const GuardianRecoveryModuleAbi = [
name: "timestamp",
type: "uint256",
},
{
internalType: "string",
name: "accountId",
type: "string",
},
],
stateMutability: "view",
type: "function",
Expand Down Expand Up @@ -325,19 +403,19 @@ export const GuardianRecoveryModuleAbi = [
type: "bool",
},
],
stateMutability: "view",
stateMutability: "pure",
type: "function",
},
{
inputs: [
{
internalType: "bytes32",
name: "signedHash",
name: "",
type: "bytes32",
},
{
internalType: "bytes",
name: "signature",
name: "",
type: "bytes",
},
],
Expand All @@ -349,19 +427,19 @@ export const GuardianRecoveryModuleAbi = [
type: "bool",
},
],
stateMutability: "view",
stateMutability: "pure",
type: "function",
},
{
inputs: [
{
internalType: "bytes32",
name: "signedHash",
name: "",
type: "bytes32",
},
{
internalType: "bytes",
name: "signature",
name: "",
type: "bytes",
},
{
Expand Down Expand Up @@ -468,7 +546,7 @@ export const GuardianRecoveryModuleAbi = [
name: "webAuthValidator",
outputs: [
{
internalType: "address",
internalType: "contract WebAuthValidator",
name: "",
type: "address",
},
Expand Down
Loading

0 comments on commit 8fe79b7

Please sign in to comment.