Skip to main content

Overview

MultiSignerManager handles transactions that require signatures from multiple signers. Access it via kit.multiSigners.
// Get all available signers (indexer-backed)
const signers = await kit.multiSigners.getAvailableSigners();

if (kit.multiSigners.needsMultiSigner(signers)) {
  const selected = kit.multiSigners.buildSelectedSigners(signers, activeCredentialId);
  await kit.multiSigners.transfer('CTOKEN...', 'GRECIPIENT...', 100, selected);
}
getAvailableSigners() is indexer-backed - it requires a configured indexer. This mirrors kit.rules.list() for the same reason: the contract does not expose an iterator over active rule IDs after deletions.

Methods

getAvailableSigners()

Discover all signers across all active context rules. Requires indexer access.
const signers = await kit.multiSigners.getAvailableSigners(); // ContractSigner[]

needsMultiSigner()

Check whether the current operation requires more than one signer.
const needs = kit.multiSigners.needsMultiSigner(signers: ContractSigner[]); // boolean

buildSelectedSigners()

Assemble a SelectedSigner[] array for use in multi-sig operations.
const selected = kit.multiSigners.buildSelectedSigners(
  signers: ContractSigner[],
  activeCredentialId?: string
);
Pass activeCredentialId to mark which passkey credential is the currently authenticated one.

transfer()

Execute a token transfer requiring signatures from multiple signers.
const result = await kit.multiSigners.transfer(
  tokenContract: string,
  recipient: string,
  amount: number | bigint | string,
  selectedSigners: SelectedSigner[]
);

operation()

Execute any assembled transaction requiring multi-signer authorization.
const result = await kit.multiSigners.operation(
  assembledTx: AssembledTransaction,
  selectedSigners: SelectedSigner[],
  options?: SubmissionOptions
);

Full Multi-Sig Example

// 1. Discover all signers
const signers = await kit.multiSigners.getAvailableSigners();

// 2. Check if multi-sig is needed
if (!kit.multiSigners.needsMultiSigner(signers)) {
  // Single signer - use the normal transfer path
  await kit.transfer(tokenContract, recipient, amount);
  return;
}

// 3. Build the signer selection
const selected = kit.multiSigners.buildSelectedSigners(
  signers,
  kit.activeCredentialId  // mark which passkey is currently authenticated
);

// 4. Execute
const result = await kit.multiSigners.transfer(tokenContract, recipient, amount, selected);

Types

import type { SelectedSigner } from 'smart-account-kit';

interface SelectedSigner {
  signer: ContractSigner;
  credentialId?: string;  // For passkey signers
  address?: string;       // For G-address signers
}