A key concept in working with smart accounts is understanding how signing works. There are two distinct types of signers you’ll work with:

Smart Account Signers (Configuration)

These define the permanent configuration of who can interact with the account:

  • Stored permanently in the smart account’s configuration
  • Each signer has specific permissions:
    • CAN_INITIATE: Create new transactions
    • CAN_VOTE: Approve pending transactions
    • CAN_EXECUTE: Execute approved transactions
  • Modified through configuration changes (add/remove signers)
  • Example: Adding a new recovery key or admin key to your smart account

Transaction Signers (Authorization)

These are used to authorize specific transactions:

  • Must be existing smart account signers
  • Must provide enough signatures to meet the threshold
  • Only used for transaction authorization, not stored
  • Example: Two admins signing a configuration change

How They Work Together

Most configuration changes require both types:

  1. transaction_signers: The keys that will sign to approve this specific change
  2. Configuration parameters: The actual changes to make (like new smart account signers)

Example

{
  "transaction_signers": ["admin1", "admin2"], // Who's authorizing this change
  "smart_account_signers": [
    // The new configuration
    {
      "address": "newSigner",
      "permissions": ["CAN_INITIATE", "CAN_VOTE"]
    }
  ]
}

Common Use Cases

Adding a New Admin

When adding a new administrator to your smart account:

  1. Smart Account Signers: The new admin’s key and their permissions
  2. Transaction Signers: Existing admins who approve adding the new admin

Removing a Compromised Key

If a key needs to be removed:

  1. Transaction Signers: Other admins sign to approve the removal
  2. Configuration Change: Remove the compromised key from smart account signers

Using Spending Limits

For daily operations:

  1. Smart Account Signers: Keys authorized to use spending limits
  2. Transaction Signers: Single authorized key executing within limits

Signing the Returned Transaction

When you make a request to any Smart Account API endpoint, you receive a base64-encoded transaction that needs to be signed by the specified transaction signers. Here’s how to handle it:

1. Decode the Transaction

First, decode the base64 transaction string you received in the response:

import { VersionedTransaction } from "@solana/web3.js";

const response = await fetch(
  "https://developer-api.squads.so/api/v0/smart_account/..."
);
const { transaction } = await response.json();

// Decode the transaction
const transaction = VersionedTransaction.deserialize(
  Buffer.from(transaction, "base64")
);

2. Collect Required Signatures

The transaction must be signed by all specified transaction signers to meet the threshold:

// Example with multiple signers
const signer1 = SIGNER_1_KEYPAIR;
const signer2 = SIGNER_2_KEYPAIR;

// Sign with each required signer
transaction.sign([signer1, signer2]);

3. Send the Signed Transaction

Once all required signatures are collected, send the transaction:

const connection = new Connection(/* your RPC endpoint */);
const signature = await connection.sendTransaction(transaction);
console.log(`Transaction sent: ${signature}`);

Common Signing Patterns

Single Signer

Most basic case, like using a spending limit:

const wallet = useWallet(); // Your wallet integration
transaction.sign([wallet]);

Multiple Signers (Sequential)

When multiple admins need to sign, but not simultaneously:

// First admin signs
transaction.sign([admin1]);

// Save and share the transaction
const serialized = transaction.serialize();

// Later, second admin signs
const finalTx = VersionedTransaction.deserialize(serialized);
finalTx.sign([admin2]);

Multiple Signers (Simultaneous)

When all signers are available at once:

const signers = [admin1, admin2];
transaction.sign(signers);

For more details on transaction handling and network interaction, see our Networking Guide.