Add, remove, and manage signers and guardians for smart accounts
import { createMultisigValidator } from "@zerodev/multisig-validator";
import { KERNEL_V3_1 } from "@zerodev/sdk/constants";
async function addSigner(
kernelClient: any,
newSigner: string,
newThreshold?: number
) {
const currentSigners = await kernelClient.account.getSigners();
console.log("Current signers:", currentSigners);
console.log("Adding new signer:", newSigner);
const updatedSigners = [...currentSigners, newSigner];
const threshold = newThreshold || currentSigners.length;
const multisigValidator = await createMultisigValidator(kernelClient.publicClient, {
signers: updatedSigners,
threshold,
entryPoint: kernelClient.account.entryPoint,
kernelVersion: KERNEL_V3_1
});
const userOpHash = await kernelClient.installPlugin({
plugin: multisigValidator
});
await kernelClient.waitForUserOperationReceipt({ hash: userOpHash });
console.log("Signer added successfully!");
console.log("New threshold:", threshold, "of", updatedSigners.length);
return userOpHash;
}
async function removeSigner(
kernelClient: any,
signerToRemove: string,
newThreshold?: number
) {
const currentSigners = await kernelClient.account.getSigners();
if (!currentSigners.includes(signerToRemove)) {
throw new Error("Signer not found");
}
const updatedSigners = currentSigners.filter(s => s !== signerToRemove);
const threshold = newThreshold || Math.min(
currentSigners.length - 1,
await kernelClient.account.getThreshold()
);
if (updatedSigners.length < threshold) {
throw new Error("Threshold would be higher than number of signers");
}
const multisigValidator = await createMultisigValidator(kernelClient.publicClient, {
signers: updatedSigners,
threshold,
entryPoint: kernelClient.account.entryPoint,
kernelVersion: KERNEL_V3_1
});
const userOpHash = await kernelClient.installPlugin({
plugin: multisigValidator
});
await kernelClient.waitForUserOperationReceipt({ hash: userOpHash });
console.log("Signer removed:", signerToRemove);
console.log("New threshold:", threshold, "of", updatedSigners.length);
return userOpHash;
}
async function updateThreshold(
kernelClient: any,
newThreshold: number
) {
const currentSigners = await kernelClient.account.getSigners();
if (newThreshold > currentSigners.length) {
throw new Error("Threshold cannot exceed number of signers");
}
if (newThreshold < 1) {
throw new Error("Threshold must be at least 1");
}
const multisigValidator = await createMultisigValidator(kernelClient.publicClient, {
signers: currentSigners,
threshold: newThreshold,
entryPoint: kernelClient.account.entryPoint,
kernelVersion: KERNEL_V3_1
});
const userOpHash = await kernelClient.installPlugin({
plugin: multisigValidator
});
await kernelClient.waitForUserOperationReceipt({ hash: userOpHash });
console.log("Threshold updated to:", newThreshold);
console.log("Total signers:", currentSigners.length);
return userOpHash;
}
async function replaceSigner(
kernelClient: any,
oldSigner: string,
newSigner: string
) {
const currentSigners = await kernelClient.account.getSigners();
if (!currentSigners.includes(oldSigner)) {
throw new Error("Old signer not found");
}
if (currentSigners.includes(newSigner)) {
throw new Error("New signer already exists");
}
const updatedSigners = currentSigners.map(s =>
s === oldSigner ? newSigner : s
);
const currentThreshold = await kernelClient.account.getThreshold();
const multisigValidator = await createMultisigValidator(kernelClient.publicClient, {
signers: updatedSigners,
threshold: currentThreshold,
entryPoint: kernelClient.account.entryPoint,
kernelVersion: KERNEL_V3_1
});
const userOpHash = await kernelClient.installPlugin({
plugin: multisigValidator
});
await kernelClient.waitForUserOperationReceipt({ hash: userOpHash });
console.log("Signer replaced");
console.log("Old:", oldSigner);
console.log("New:", newSigner);
return userOpHash;
}