Generate a multisig signature
The Smart Accounts KitSmart Accounts Kit Toolkit for creating, managing, and interacting with MetaMask Smart Accounts, delegations, and Advanced Permissions. supports Multisig smart accounts,
allowing you to add multiple EOAExternally owned account (EOA) A private-key-controlled account with no built-in programmable execution logic.
signersSigner An account that can sign transactions for a smart account. with a configurable execution threshold. When the threshold
is greater than 1, you can collect signatures from the required signers
and use the aggregateSignature function to combine them
into a single aggregated signature.
Prerequisites
Generate a multisig signature
The following example configures a Multisig smart account with two different signers: Alice and Bob. The account has a threshold of 2, meaning that signatures from both parties are required for any execution.
- example.ts
- config.ts
import {
bundlerClient,
aliceSmartAccount,
bobSmartAccount,
aliceAccount,
bobAccount,
} from "./config.ts";
import { aggregateSignature } from "@metamask/smart-accounts-kit";
const userOperation = await bundlerClient.prepareUserOperation({
account: aliceSmartAccount,
calls: [
{
target: zeroAddress,
value: 0n,
data: "0x",
}
]
});
const aliceSignature = await aliceSmartAccount.signUserOperation(userOperation);
const bobSignature = await bobSmartAccount.signUserOperation(userOperation);
const aggregatedSignature = aggregateSignature({
signatures: [{
signer: aliceAccount.address,
signature: aliceSignature,
type: "ECDSA",
}, {
signer: bobAccount.address,
signature: bobSignature,
type: "ECDSA",
}],
});
import { createPublicClient, http } from "viem";
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
import { createBundlerClient } from "viem/account-abstraction";
import { sepolia as chain } from "viem/chains";
import {
Implementation,
toMetaMaskSmartAccount,
} from "@metamask/smart-accounts-kit";
const publicClient = createPublicClient({
chain,
transport: http()
});
const alicePrivateKey = generatePrivateKey();
export const aliceAccount = privateKeyToAccount(alicePrivateKey);
const bobPrivateKey = generatePrivateKey();
export const bobAccount = privateKeyToAccount(bobPrivateKey)
const signers = [ aliceAccount.address, bobAccount.address ];
const threshold = 2n
export const aliceSmartAccount = await toMetaMaskSmartAccount({
client: publicClient,
implementation: Implementation.MultiSig,
deployParams: [signers, threshold],
deploySalt: "0x",
signer: [ { account: aliceAccount } ],
});
export const bobSmartAccount = await toMetaMaskSmartAccount({
client: publicClient,
implementation: Implementation.MultiSig,
deployParams: [signers, threshold],
deploySalt: "0x",
signer: [ { account: bobAccount } ],
});
export const bundlerClient = createBundlerClient({
client: publicClient,
transport: http("https://public.pimlico.io/v2/rpc")
});