Manage multiple signers for your smart accounts to enable multi-signature security with Para’s AA infrastructure.

Prerequisites

You need a deployed smart account with multi-signature support.

Create Smart Account

Add Signers

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;
}

Remove Signers

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;
}

Update Threshold

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;
}

Replace Signer

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;
}

Next Steps