or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

account-management.mdcore-primitives.mdcryptography.mdencoding-codecs.mderror-handling.mdhigh-level-utilities.mdindex.mdinstructions-programs.mdrpc-communication.mdsigning-authentication.mdtransaction-building.md
tile.json

signing-authentication.mddocs/

Signing and Authentication

Transaction and message signing with support for multiple signers, partial signing workflows, and authentication patterns.

Capabilities

Signer Interfaces

Core signer abstractions for different signing scenarios.

/**
 * Can sign complete transactions
 */
interface TransactionSigner<TAddress = Address> {
  address: TAddress;
  signTransaction<TTransaction extends TransactionWithSignatures>(
    transaction: TTransaction
  ): Promise<TTransaction>;
}

/**
 * Can modify and sign transactions (e.g., add instructions)
 */
interface TransactionModifyingSigner<TAddress = Address> {
  address: TAddress;
  modifyAndSignTransaction<TTransaction extends TransactionWithSignatures>(
    transaction: TTransaction,
    config?: TransactionModificationConfig
  ): Promise<TTransaction>;
}

/**
 * Can partially sign transactions in multi-sig scenarios
 */
interface TransactionPartialSigner<TAddress = Address> {
  address: TAddress;
  signTransaction<TTransaction extends TransactionWithSignatures>(
    transaction: TTransaction
  ): Promise<TTransaction>;
}

/**
 * Can send transactions directly
 */
interface TransactionSendingSigner<TAddress = Address> extends TransactionSigner<TAddress> {
  sendTransaction<TTransaction extends TransactionWithSignatures>(
    transaction: TTransaction,
    config?: SendTransactionConfig
  ): Promise<Signature>;
}

/**
 * Can sign arbitrary messages
 */
interface MessageSigner<TAddress = Address> {
  address: TAddress;
  signMessage(message: Uint8Array): Promise<SignatureBytes>;
}

/**
 * Can modify and sign messages
 */
interface MessageModifyingSigner<TAddress = Address> extends MessageSigner<TAddress> {
  modifyAndSignMessage(
    message: Uint8Array,
    config?: MessageModificationConfig
  ): Promise<{ message: Uint8Array; signature: SignatureBytes }>;
}

/**
 * Can partially sign messages
 */
interface MessagePartialSigner<TAddress = Address> extends MessageSigner<TAddress> {
  signMessage(message: Uint8Array): Promise<SignatureBytes>;
}

Signer Implementations

Concrete signer implementations for different key sources.

/**
 * Signer using CryptoKey pair
 */
interface KeypairSigner extends TransactionSigner, MessageSigner {
  address: Address;
  privateKey: CryptoKey;
  publicKey: CryptoKey;
}

/**
 * Create signer from CryptoKey pair
 * @param keyPair - Ed25519 key pair
 * @returns Signer implementation
 */
function createSignerFromKeyPair(keyPair: CryptoKeyPair): Promise<KeypairSigner>;

/**
 * No-operation signer for testing
 */
interface NoopSigner extends TransactionSigner, MessageSigner {
  address: Address;
}

/**
 * Create no-op signer that doesn't actually sign
 * @param address - Signer address
 * @returns No-op signer for testing
 */
function createNoopSigner(address: Address): NoopSigner;

Usage Examples:

import { 
  generateKeyPair,
  createSignerFromKeyPair,
  getAddressFromPublicKey
} from "@solana/web3.js";

// Create signer from generated key pair
const keyPair = await generateKeyPair();
const signer = await createSignerFromKeyPair(keyPair);

console.log("Signer address:", signer.address);

// Sign a message
const message = new TextEncoder().encode("Hello, Solana!");
const signature = await signer.signMessage(message);
console.log("Message signature:", signature);

Transaction Signing

Add signatures to transactions and manage signing workflows.

/**
 * Add signers to a transaction or message
 * @param transaction - Transaction to add signers to
 * @param signers - Array of signers to add
 * @returns Transaction with signers added
 */
function addSigners<T extends TransactionMessage | Transaction>(
  transaction: T,
  signers: TransactionSigner[]
): T;

/**
 * Sign transaction with provided signers
 * @param transaction - Transaction to sign
 * @param signers - Signers to use
 * @returns Promise resolving to signed transaction
 */
function signTransaction<TTransaction extends TransactionWithSignatures>(
  transaction: TTransaction,
  signers: TransactionSigner[]
): Promise<TTransaction>;

/**
 * Partially sign transaction (for multi-sig workflows)
 * @param transaction - Transaction to partially sign
 * @param signer - Signer to add signature
 * @returns Promise resolving to transaction with additional signature
 */
function partiallySignTransaction<TTransaction extends TransactionWithSignatures>(
  transaction: TTransaction,
  signer: TransactionPartialSigner
): Promise<TTransaction>;

/**
 * Check if transaction is fully signed
 * @param transaction - Transaction to check
 * @returns True if all required signatures are present
 */
function isTransactionFullySigned(transaction: TransactionWithSignatures): boolean;

/**
 * Get missing signers from transaction
 * @param transaction - Transaction to analyze
 * @returns Array of addresses that still need to sign
 */
function getMissingSigners(transaction: TransactionWithSignatures): Address[];

Usage Examples:

import {
  createTransactionMessage,
  compileTransaction,
  signTransaction,
  addSigners,
  isTransactionFullySigned
} from "@solana/web3.js";

// Create transaction
const message = createTransactionMessage({
  version: 0,
  feePayer: signer.address,
  blockhash,
  instructions: [/* instructions */]
});

let transaction = compileTransaction(message);

// Add signers
transaction = addSigners(transaction, [signer]);

// Sign transaction
const signedTransaction = await signTransaction(transaction, [signer]);

// Check if fully signed
console.log("Fully signed:", isTransactionFullySigned(signedTransaction));

Multi-Signature Workflows

Handle transactions requiring multiple signatures.

/**
 * Multi-signature transaction builder
 */
interface MultiSigTransaction {
  /** Transaction being signed */
  transaction: TransactionWithSignatures;
  /** Required signers */
  requiredSigners: Address[];
  /** Current signatures */
  signatures: Map<Address, SignatureBytes>;
  /** Whether transaction is ready to send */
  isComplete: boolean;
}

/**
 * Create multi-signature transaction
 * @param transaction - Base transaction
 * @param requiredSigners - Addresses that must sign
 * @returns Multi-sig transaction builder
 */
function createMultiSigTransaction(
  transaction: TransactionWithSignatures,
  requiredSigners: Address[]
): MultiSigTransaction;

/**
 * Add signature to multi-sig transaction
 * @param multiSigTx - Multi-sig transaction
 * @param signer - Signer to add
 * @returns Updated multi-sig transaction
 */
function addSignatureToMultiSig(
  multiSigTx: MultiSigTransaction,
  signer: TransactionSigner
): Promise<MultiSigTransaction>;

/**
 * Finalize multi-sig transaction when all signatures collected
 * @param multiSigTx - Completed multi-sig transaction
 * @returns Fully signed transaction ready to send
 */
function finalizeMultiSigTransaction(
  multiSigTx: MultiSigTransaction
): TransactionWithSignatures;

Fee Payer Management

Handle fee payer designation and signing requirements.

/**
 * Fee payer signer interface
 */
interface FeePayerSigner extends TransactionSigner {
  /** Indicates this signer can pay fees */
  canPayFees: boolean;
}

/**
 * Set fee payer for transaction
 * @param transaction - Transaction to modify
 * @param feePayer - Fee payer signer
 * @returns Transaction with fee payer set
 */
function setFeePayer<T extends TransactionMessage | Transaction>(
  transaction: T,
  feePayer: FeePayerSigner
): T;

/**
 * Get fee payer from transaction
 * @param transaction - Transaction to analyze
 * @returns Fee payer address
 */
function getFeePayer(transaction: TransactionMessage | Transaction): Address;

/**
 * Estimate transaction fee
 * @param transaction - Transaction to estimate
 * @param rpc - RPC client for fee calculation
 * @returns Estimated fee in lamports
 */
function estimateTransactionFee(
  transaction: TransactionWithSignatures,
  rpc: Rpc<GetFeeForMessageApi>
): Promise<Lamports>;

Signature Verification

Verify signatures and validate signing requirements.

/**
 * Verify transaction signatures
 * @param transaction - Signed transaction
 * @returns Promise resolving to verification result
 */
function verifyTransactionSignatures(
  transaction: TransactionWithSignatures
): Promise<{
  valid: boolean;
  invalidSignatures: Address[];
}>;

/**
 * Verify message signature
 * @param message - Original message
 * @param signature - Signature to verify
 * @param publicKey - Public key of signer
 * @returns Promise resolving to true if valid
 */
function verifyMessageSignature(
  message: Uint8Array,
  signature: SignatureBytes,
  publicKey: CryptoKey
): Promise<boolean>;

/**
 * Extract signer addresses from transaction
 * @param transaction - Transaction to analyze
 * @returns Array of required signer addresses
 */
function extractSigners(transaction: TransactionMessage | Transaction): Address[];

Types and Configuration

/**
 * Transaction with signature storage
 */
interface TransactionWithSignatures {
  /** Transaction signatures */
  signatures: Signature[];
  /** Other transaction properties */
  [key: string]: unknown;
}

/**
 * Configuration for transaction modification
 */
interface TransactionModificationConfig {
  /** Additional instructions to add */
  additionalInstructions?: IInstruction[];
  /** Whether to replace existing instructions */
  replaceInstructions?: boolean;
  /** Custom fee payer */
  feePayer?: Address;
}

/**
 * Configuration for message modification
 */
interface MessageModificationConfig {
  /** Additional data to append */
  additionalData?: Uint8Array;
  /** Custom prefix */
  prefix?: string;
}

/**
 * Configuration for sending transactions
 */
interface SendTransactionConfig {
  /** Skip preflight checks */
  skipPreflight?: boolean;
  /** Commitment level for confirmation */
  commitment?: Commitment;
  /** Maximum retries */
  maxRetries?: number;
}

/**
 * Signer metadata
 */
interface SignerMeta {
  /** Signer address */
  address: Address;
  /** Signer capabilities */
  capabilities: {
    canSignTransactions: boolean;
    canSignMessages: boolean;
    canModifyTransactions: boolean;
    canSendTransactions: boolean;
  };
}

Advanced Usage Examples:

import {
  createMultiSigTransaction,
  addSignatureToMultiSig,
  finalizeMultiSigTransaction,
  verifyTransactionSignatures
} from "@solana/web3.js";

// Multi-signature workflow
const requiredSigners = [signer1.address, signer2.address, signer3.address];
let multiSigTx = createMultiSigTransaction(transaction, requiredSigners);

// Collect signatures from different signers
multiSigTx = await addSignatureToMultiSig(multiSigTx, signer1);
multiSigTx = await addSignatureToMultiSig(multiSigTx, signer2);
multiSigTx = await addSignatureToMultiSig(multiSigTx, signer3);

// Finalize when all signatures collected
if (multiSigTx.isComplete) {
  const finalTransaction = finalizeMultiSigTransaction(multiSigTx);
  
  // Verify signatures before sending
  const verification = await verifyTransactionSignatures(finalTransaction);
  if (verification.valid) {
    // Send transaction
    const signature = await rpc.sendTransaction(finalTransaction).send();
    console.log("Multi-sig transaction sent:", signature);
  }
}