> ## Documentation Index
> Fetch the complete documentation index at: https://swig-tracy-multiple-subaccounts-support.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Sub Accounts in Swig

> \"Its sub accounts all the way down\" - Ancient Swig Proverb

This guide explains how to work with sub accounts in Swig, which allow authorities to create and manage dedicated sub account addresses with specific permissions. Sub accounts are perfect for use cases like portfolio management where you want to delegate complex operations without giving control over all assets.

You can find complete working examples in the Swig repository:

* [Classic Example](https://github.com/anagrambuild/swig-ts/blob/main/examples/classic/transfer/transfer-svm-subaccount.ts)
* [Kit Example](https://github.com/anagrambuild/swig-ts/blob/main/examples/kit/transfer/transfer-local-subaccount.ts)
* [Multiple SubAccounts Classic Example](https://github.com/anagrambuild/swig-ts/blob/main/examples/classic/transfer/multi-subaccount-svm.ts)
* [Multiple SubAccounts Kit Example](https://github.com/anagrambuild/swig-ts/blob/main/examples/kit/transfer/multi-subaccount-local.ts)

## What are Sub Accounts?

Sub accounts in Swig allow an authority to create and manage multiple sub account addresses (up to 255 per role) and perform any actions on behalf of those sub accounts. This is a super high level of permission so use with care. It works for use cases like portfolio management, where you want to allow an unlimited complexity of actions on behalf of specific addresses, but you don't want to give the authority control over all the assets of the swig. The root authority can always pull funds (SOL and tokens) from the sub accounts back to the main Swig wallet.

<Note>
  **New in v1.4.0**: Each role can now have up to 255 subaccounts (indices 0-254). This enables advanced use cases like:

  * Multiple isolated trading strategies per authority
  * Separate subaccounts for different asset classes
  * Per-client subaccounts in custodial scenarios
</Note>

A great example of this is Breeze, Anagram's onchain yield optimizer. Breeze can optimize the yield of a user's portfolio without giving them control over their whole swig.

## How Sub Accounts Work

To work with sub accounts, there are several key steps:

1. **Sub Account Permission**: The authority must have the sub account permission(s) to create sub account(s). This permission is set when creating or modifying a role. Each subaccount index (0-254) requires its own permission.
2. **Create Sub Account**: Once the authority has the permission, they can create a sub account using `getCreateSubAccountInstructions` with an optional `subAccountIndex` parameter.
3. **Sub Account Sign**: Once created, sub accounts can perform on-chain actions using the `getSignInstructions` with the `isSubAccount` parameter set to `true` and the `subAccountIndex` specified.

<Warning>
  **Critical Requirement**: Creating a subaccount requires a **two-step process**:

  1. **First**: Add one or more `SubAccount` permissions to a new or existing Authority on your Swig wallet. Each permission corresponds to a specific subaccount index.
  2. **Second**: Create the actual subaccount(s), which populates each blank SubAccount action with the subaccount's public key

  **Important**: Even if an authority has `All` permission, you **must** explicitly add the `SubAccount` permission(s) with blank subaccount(s) (`[0; 32]` in Rust, or using `Actions.set().subAccount(index).get()` in TypeScript) to enable subaccount creation. The `All` permission alone is not sufficient for subaccount creation.

  **Multiple SubAccounts**: To create multiple subaccounts for a role, add multiple SubAccount actions with different indices:

  * TypeScript: `Actions.set().subAccount(0).subAccount(1).subAccount(2).get()`
  * Rust: `vec![Permission::SubAccount { sub_account: [0; 32] }, ...]` (one per index, populated when created)
</Warning>

## Creating a Sub Account Authority

First, you need to add an authority with sub account permissions:

<Tabs>
  <Tab title="Classic">
    ```typescript theme={null}
    import {
      Keypair,
      LAMPORTS_PER_SOL,
    } from '@solana/web3.js';
    import {
      Actions,
      createEd25519AuthorityInfo,
      findSwigPda,
      getAddAuthorityInstructions,
      getCreateSwigInstruction,
      fetchSwig,
    } from '@swig-wallet/classic';

    // Create authorities
    const rootAuthority = Keypair.generate();
    const subAccountAuthority = Keypair.generate();

    // Create Swig with root authority
    const id = Uint8Array.from(Array(32).fill(2));
    const swigAddress = findSwigPda(id);

    const createSwigIx = await getCreateSwigInstruction({
      payer: rootAuthority.publicKey,
      actions: Actions.set().all().get(),
      authorityInfo: createEd25519AuthorityInfo(rootAuthority.publicKey),
      id,
    });

    // Add sub account authority with sub account permissions
    const swig = await fetchSwig(connection, swigAddress);
    const rootRole = swig.roles[0];

    // Add authority with single subaccount permission (index 0, default)
    const addAuthorityIx = await getAddAuthorityInstructions(
      swig,
      rootRole.id,
      createEd25519AuthorityInfo(subAccountAuthority.publicKey),
      Actions.set().subAccount().get(), // Defaults to index 0
    );

    // Or add authority with multiple subaccount permissions
    const addMultiSubAccountIx = await getAddAuthorityInstructions(
      swig,
      rootRole.id,
      createEd25519AuthorityInfo(subAccountAuthority.publicKey),
      Actions.set()
        .subAccount(0) // Allow creating subaccount at index 0
        .subAccount(1) // Allow creating subaccount at index 1
        .subAccount(2) // Allow creating subaccount at index 2
        .get(),
    );
    ```
  </Tab>

  <Tab title="Kit">
    ```typescript theme={null}
    import {
      generateKeyPairSigner,
      lamports,
    } from '@solana/kit';
    import {
      Actions,
      createEd25519AuthorityInfo,
      findSwigPda,
      getAddAuthorityInstructions,
      getCreateSwigInstruction,
      fetchSwig,
    } from '@swig-wallet/kit';

    // Create authorities
    const rootAuthority = await generateKeyPairSigner();
    const subAccountAuthority = await generateKeyPairSigner();

    // Create Swig with root authority
    const id = randomBytes(32);
    const swigAddress = await findSwigPda(id);

    const createSwigIx = await getCreateSwigInstruction({
      payer: rootAuthority.address,
      actions: Actions.set().all().get(),
      authorityInfo: createEd25519AuthorityInfo(rootAuthority.address),
      id,
    });

    // Add sub account authority with sub account permissions
    const swig = await fetchSwig(connection.rpc, swigAddress);
    const rootRole = swig.roles[0];

    // Add authority with single subaccount permission (index 0, default)
    const addAuthorityIx = await getAddAuthorityInstructions(
      swig,
      rootRole.id,
      createEd25519AuthorityInfo(subAccountAuthority.address),
      Actions.set().subAccount().get(), // Defaults to index 0
    );

    // Or add authority with multiple subaccount permissions
    const addMultiSubAccountIx = await getAddAuthorityInstructions(
      swig,
      rootRole.id,
      createEd25519AuthorityInfo(subAccountAuthority.address),
      Actions.set()
        .subAccount(0) // Allow creating subaccount at index 0
        .subAccount(1) // Allow creating subaccount at index 1
        .subAccount(2) // Allow creating subaccount at index 2
        .get(),
    );
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    use solana_program::pubkey::Pubkey;
    use solana_sdk::{
        message::{v0, VersionedMessage},
        signature::Keypair,
        transaction::VersionedTransaction,
    };
    use swig_sdk::{
        SwigInstructionBuilder,
        client_role::Ed25519ClientRole,
        types::Permission,
        AuthorityType,
    };

    // Create keypairs for authorities
    let root_authority = Keypair::new();
    let sub_account_authority = Keypair::new();
    let fee_payer = Keypair::new();

    // Generate a unique Swig wallet ID
    let swig_id = rand::random::<[u8; 32]>();

    // Step 1: Create the Swig account with root authority
    let mut root_builder = SwigInstructionBuilder::new(
        swig_id,
        Box::new(Ed25519ClientRole::new(root_authority.pubkey())),
        fee_payer.pubkey(),
        0, // root role_id
    );

    let create_swig_ix = root_builder.build_swig_account()?;

    // Send transaction to create Swig account
    // ... (compile message, sign, send transaction)

    // Step 2: Add a new authority with SubAccount permission
    // 
    // IMPORTANT: You must include the blank SubAccount permission(s) even if
    // you're also granting All permission. Each blank SubAccount action
    // (with sub_account: [0; 32]) will be populated when the corresponding
    // subaccount is created at that index.

    // Single subaccount (index 0, default)
    let add_authority_ix = root_builder.add_authority_instruction(
        AuthorityType::Ed25519,
        &sub_account_authority.pubkey().to_bytes(),
        vec![
            Permission::SubAccount {
                sub_account: [0; 32], // Blank - will be populated on creation at index 0
            },
        ],
        None, // current_slot not required for Ed25519
    )?;

    // Multiple subaccounts (indices 0, 1, 2)
    let add_multi_subaccount_ix = root_builder.add_authority_instruction(
        AuthorityType::Ed25519,
        &sub_account_authority.pubkey().to_bytes(),
        vec![
            Permission::SubAccount { sub_account: [0; 32] }, // Index 0
            Permission::SubAccount { sub_account: [0; 32] }, // Index 1
            Permission::SubAccount { sub_account: [0; 32] }, // Index 2
        ],
        None,
    )?;

    // If you want to grant All permission AND SubAccount permissions:
    let add_authority_with_all_ix = root_builder.add_authority_instruction(
        AuthorityType::Ed25519,
        &sub_account_authority.pubkey().to_bytes(),
        vec![
            Permission::All,
            Permission::SubAccount { sub_account: [0; 32] }, // REQUIRED even with All
        ],
        None,
    )?;

    // Send transaction to add authority
    // ... (compile message, sign with root_authority, send transaction)
    ```
  </Tab>
</Tabs>

## Creating Sub Accounts

Once you have an authority with sub account permissions, you can create the sub account(s). Each subaccount is identified by an index (0-254).

<Tabs>
  <Tab title="Classic">
    ```typescript theme={null}
    import {
      findSwigSubAccountPda,
      findSwigSubAccountPdaWithIndex,
      getCreateSubAccountInstructions,
    } from '@swig-wallet/classic';

    // Refetch swig to get updated roles
    await swig.refetch();
    const subAccountAuthRole = swig.roles[1];

    // Create sub account at index 0 (default, backwards compatible)
    const createSubAccount0Ix = await getCreateSubAccountInstructions(
      swig,
      subAccountAuthRole.id,
      { subAccountIndex: 0 }, // Optional, defaults to 0
    );
    await sendTransaction(connection, createSubAccount0Ix, subAccountAuthority);

    // Get the sub account address for index 0
    // Both methods work for index 0 (backwards compatible)
    const subAccount0Legacy = findSwigSubAccountPda(
      subAccountAuthRole.swigId,
      subAccountAuthRole.id,
    );
    const subAccount0New = findSwigSubAccountPdaWithIndex(
      subAccountAuthRole.swigId,
      subAccountAuthRole.id,
      0,
    );
    // These addresses are identical for index 0

    // Create additional sub accounts at different indices
    const createSubAccount1Ix = await getCreateSubAccountInstructions(
      swig,
      subAccountAuthRole.id,
      { subAccountIndex: 1 },
    );
    await sendTransaction(connection, createSubAccount1Ix, subAccountAuthority);

    const subAccount1 = findSwigSubAccountPdaWithIndex(
      subAccountAuthRole.swigId,
      subAccountAuthRole.id,
      1,
    );

    // Create sub account at index 2
    const createSubAccount2Ix = await getCreateSubAccountInstructions(
      swig,
      subAccountAuthRole.id,
      { subAccountIndex: 2 },
    );
    await sendTransaction(connection, createSubAccount2Ix, subAccountAuthority);

    const subAccount2 = findSwigSubAccountPdaWithIndex(
      subAccountAuthRole.swigId,
      subAccountAuthRole.id,
      2,
    );
    ```
  </Tab>

  <Tab title="Kit">
    ```typescript theme={null}
    import {
      findSwigSubAccountPda,
      findSwigSubAccountPdaWithIndex,
      getCreateSubAccountInstructions,
    } from '@swig-wallet/kit';

    // Refetch swig to get updated roles
    await swig.refetch();
    const subAccountAuthRole = swig.roles[1];

    // Create sub account at index 0 (default, backwards compatible)
    const createSubAccount0Ix = await getCreateSubAccountInstructions(
      swig,
      subAccountAuthRole.id,
      { 
        payer: subAccountAuthority.address,
        subAccountIndex: 0, // Optional, defaults to 0
      },
    );
    await sendTransaction(connection, createSubAccount0Ix, subAccountAuthority);

    // Get the sub account address for index 0
    // Both methods work for index 0 (backwards compatible)
    const subAccount0Legacy = await findSwigSubAccountPda(
      subAccountAuthRole.swigId,
      subAccountAuthRole.id,
    );
    const subAccount0New = await findSwigSubAccountPdaWithIndex(
      subAccountAuthRole.swigId,
      subAccountAuthRole.id,
      0,
    );
    // These addresses are identical for index 0

    // Create additional sub accounts at different indices
    const createSubAccount1Ix = await getCreateSubAccountInstructions(
      swig,
      subAccountAuthRole.id,
      { 
        payer: subAccountAuthority.address,
        subAccountIndex: 1,
      },
    );
    await sendTransaction(connection, createSubAccount1Ix, subAccountAuthority);

    const subAccount1 = await findSwigSubAccountPdaWithIndex(
      subAccountAuthRole.swigId,
      subAccountAuthRole.id,
      1,
    );

    // Create sub account at index 2
    const createSubAccount2Ix = await getCreateSubAccountInstructions(
      swig,
      subAccountAuthRole.id,
      { 
        payer: subAccountAuthority.address,
        subAccountIndex: 2,
      },
    );
    await sendTransaction(connection, createSubAccount2Ix, subAccountAuthority);

    const subAccount2 = await findSwigSubAccountPdaWithIndex(
      subAccountAuthRole.swigId,
      subAccountAuthRole.id,
      2,
    );
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    use solana_program::pubkey::Pubkey;
    use solana_sdk::{
        message::{v0, VersionedMessage},
        signature::Keypair,
        transaction::VersionedTransaction,
    };
    use swig_sdk::{
        SwigInstructionBuilder,
        client_role::Ed25519ClientRole,
    };
    use swig_interface::derive_sub_account_pda;
    use swig_interface::program_id;

    // Step 1: Get the role ID of the newly added authority
    // In production, you would fetch the Swig account and look up the role ID
    // For this example, we know it will be role_id 1 (first added authority)
    let sub_account_role_id = 1;

    // Step 2: Create the subaccount builder
    let mut sub_account_builder = SwigInstructionBuilder::new(
        swig_id,
        Box::new(Ed25519ClientRole::new(sub_account_authority.pubkey())),
        fee_payer.pubkey(),
        sub_account_role_id,
    );

    // Create subaccount at index 0 (default, backwards compatible)
    let create_sub_account_0_ix = sub_account_builder.create_sub_account_with_index(
        0, // Index 0 uses legacy PDA derivation
    )?;

    // Send transaction
    let recent_blockhash = rpc_client.get_latest_blockhash()?;
    let msg = v0::Message::try_compile(
        &fee_payer.pubkey(),
        &[create_sub_account_0_ix],
        &[],
        recent_blockhash,
    )?;
    let tx = VersionedTransaction::try_new(
        VersionedMessage::V0(msg),
        &[fee_payer, &sub_account_authority],
    )?;
    rpc_client.send_and_confirm_transaction(&tx)?;

    // Derive the subaccount address for index 0
    let (sub_account_0, _) = derive_sub_account_pda(&swig_id, sub_account_role_id, 0);
    println!("Subaccount 0 created at: {}", sub_account_0);

    // Create additional subaccounts at different indices
    let create_sub_account_1_ix = sub_account_builder.create_sub_account_with_index(1)?;
    // ... send transaction ...
    let (sub_account_1, _) = derive_sub_account_pda(&swig_id, sub_account_role_id, 1);

    let create_sub_account_2_ix = sub_account_builder.create_sub_account_with_index(2)?;
    // ... send transaction ...
    let (sub_account_2, _) = derive_sub_account_pda(&swig_id, sub_account_role_id, 2);

    println!("Created subaccounts: {}, {}, {}", sub_account_0, sub_account_1, sub_account_2);
    ```
  </Tab>
</Tabs>

## Creating Swig Account and SubAccount in One Transaction

If you're creating a new Swig wallet and want to set up a subaccount immediately, you can create both the Swig account with subaccount authority and the subaccount itself in a single transaction. This reduces the number of transactions needed from 3 to 1.

<Tabs>
  <Tab title="Rust">
    ```rust theme={null}
    use solana_program::pubkey::Pubkey;
    use solana_sdk::{
        message::{v0, VersionedMessage},
        signature::Keypair,
        transaction::VersionedTransaction,
    };
    use swig_interface::{
        AuthorityConfig, ClientAction, CreateInstruction, CreateSubAccountInstruction,
    };
    use swig_state::{
        action::{all::All, sub_account::SubAccount},
        authority::AuthorityType,
        swig::{sub_account_seeds, swig_account_seeds, swig_wallet_address_seeds},
    };

    fn create_swig_and_subaccount_in_one_tx(
        rpc_client: &RpcClient,
        authority: &Keypair,
        fee_payer: &Keypair,
    ) -> Result<(Pubkey, Pubkey), Box<dyn std::error::Error>> {
        let swig_id = rand::random::<[u8; 32]>();
        let program_id = swig_interface::program_id();

        // Derive the Swig account address
        let (swig_key, swig_bump) =
            Pubkey::find_program_address(&swig_account_seeds(&swig_id), &program_id);
        let (swig_wallet_address, wallet_address_bump) = Pubkey::find_program_address(
            &swig_wallet_address_seeds(swig_key.as_ref()),
            &program_id,
        );

        // Derive the sub-account address (role_id 0 since this is the initial authority)
        let role_id: u32 = 0;
        let role_id_bytes = role_id.to_le_bytes();
        let (sub_account, sub_account_bump) =
            Pubkey::find_program_address(&sub_account_seeds(&swig_id, &role_id_bytes), &program_id);

        // Step 1: Create instruction to create Swig account with All + SubAccount permissions
        let create_swig_ix = CreateInstruction::new(
            swig_key,
            swig_bump,
            fee_payer.pubkey(),
            swig_wallet_address,
            wallet_address_bump,
            AuthorityConfig {
                authority_type: AuthorityType::Ed25519,
                authority: authority.pubkey().as_ref(),
            },
            vec![
                ClientAction::All(All {}),
                ClientAction::SubAccount(SubAccount::new_for_creation()),
            ],
            swig_id,
        )?;

        // Step 2: Create instruction to create the subaccount
        // This uses role_id 0 since the authority is the initial/root authority
        let create_sub_account_ix = CreateSubAccountInstruction::new_with_ed25519_authority(
            swig_key,
            authority.pubkey(),
            fee_payer.pubkey(),
            sub_account,
            role_id,
            sub_account_bump,
        )?;

        // Step 3: Submit both instructions in a single transaction
        let recent_blockhash = rpc_client.get_latest_blockhash()?;
        let message = v0::Message::try_compile(
            &fee_payer.pubkey(),
            &[create_swig_ix, create_sub_account_ix],
            &[],
            recent_blockhash,
        )?;

        let tx = VersionedTransaction::try_new(
            VersionedMessage::V0(message),
            &[fee_payer, authority],
        )?;

        rpc_client.send_and_confirm_transaction(&tx)?;

        // Verify both accounts were created
        let swig_account = rpc_client.get_account(&swig_key)?;
        let sub_account_data = rpc_client.get_account(&sub_account)?;
        
        assert_eq!(sub_account_data.owner, solana_sdk::system_program::id());

        Ok((swig_key, sub_account))
    }
    ```
  </Tab>
</Tabs>

**Note**: This approach attempts to create both the Swig account and subaccount atomically in a single transaction. While this can be more efficient, it may fail if the subaccount creation instruction requires the Swig account to be fully initialized and written to the blockchain first. If this fails, fall back to the multi-transaction approach shown in the previous examples.

## Using Sub Accounts

Once created, you can use the sub account to perform transactions:

<Tabs>
  <Tab title="Classic">
    ```typescript theme={null}
    import {
      SystemProgram,
      LAMPORTS_PER_SOL,
    } from '@solana/web3.js';
    import {
      getSignInstructions,
    } from '@swig-wallet/classic';

    // Fund the sub account
    await connection.requestAirdrop(subAccountAddress, LAMPORTS_PER_SOL);

    // Create a transfer from the sub account
    const recipient = Keypair.generate().publicKey;

    const transfer = SystemProgram.transfer({
      fromPubkey: subAccountAddress,
      toPubkey: recipient,
      lamports: 0.1 * LAMPORTS_PER_SOL,
    });

    // Sign with sub account at index 0 (default)
    const signIx = await getSignInstructions(
      swig,
      subAccountAuthRole.id,
      [transfer],
      true, // isSubAccount flag
      { subAccountIndex: 0 }, // Optional, defaults to 0
    );

    await sendTransaction(connection, signIx, subAccountAuthority);

    // To use a different subaccount index:
    const transfer1 = SystemProgram.transfer({
      fromPubkey: subAccount1, // subaccount at index 1
      toPubkey: recipient,
      lamports: 0.1 * LAMPORTS_PER_SOL,
    });

    const signIx1 = await getSignInstructions(
      swig,
      subAccountAuthRole.id,
      [transfer1],
      true,
      { subAccountIndex: 1 }, // Use subaccount at index 1
    );

    await sendTransaction(connection, signIx1, subAccountAuthority);
    ```
  </Tab>

  <Tab title="Kit">
    ```typescript theme={null}
    import {
      getTransferSolInstructionDataEncoder,
      SYSTEM_PROGRAM_ADDRESS,
    } from '@solana-program/system';
    import {
      AccountRole,
      generateKeyPairSigner,
      lamports,
    } from '@solana/kit';
    import {
      getSignInstructions,
    } from '@swig-wallet/kit';

    // Fund the sub account
    await connection.rpc
      .requestAirdrop(subAccountAddress, lamports(BigInt(LAMPORTS_PER_SOL)))
      .send();

    // Create a transfer from the sub account
    const recipient = (await generateKeyPairSigner()).address;

    const transfer = {
      programAddress: SYSTEM_PROGRAM_ADDRESS,
      accounts: [
        {
          address: subAccountAddress,
          role: AccountRole.WRITABLE_SIGNER,
        },
        {
          address: recipient,
          role: AccountRole.WRITABLE,
        },
      ],
      data: new Uint8Array(
        getTransferSolInstructionDataEncoder().encode({
          amount: 0.1 * LAMPORTS_PER_SOL,
        }),
      ),
    };

    // Sign with sub account at index 0 (default)
    const signIx = await getSignInstructions(
      swig,
      subAccountAuthRole.id,
      [transfer],
      true, // isSubAccount flag
      { 
        payer: subAccountAuthority.address,
        subAccountIndex: 0, // Optional, defaults to 0
      },
    );

    await sendTransaction(connection, signIx, subAccountAuthority);

    // To use a different subaccount index:
    const transfer1 = {
      programAddress: SYSTEM_PROGRAM_ADDRESS,
      accounts: [
        { address: subAccount1, role: AccountRole.WRITABLE_SIGNER },
        { address: recipient, role: AccountRole.WRITABLE },
      ],
      data: new Uint8Array(
        getTransferSolInstructionDataEncoder().encode({
          amount: 0.1 * LAMPORTS_PER_SOL,
        }),
      ),
    };

    const signIx1 = await getSignInstructions(
      swig,
      subAccountAuthRole.id,
      [transfer1],
      true,
      { 
        payer: subAccountAuthority.address,
        subAccountIndex: 1, // Use subaccount at index 1
      },
    );

    await sendTransaction(connection, signIx1, subAccountAuthority);
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    use solana_program::{
        instruction::Instruction,
        pubkey::Pubkey,
        system_instruction,
    };
    use solana_sdk::{
        message::{v0, VersionedMessage},
        signature::Keypair,
        transaction::VersionedTransaction,
    };
    use swig_sdk::{
        SwigInstructionBuilder,
        client_role::Ed25519ClientRole,
    };

    // Fund the sub account
    rpc_client.request_airdrop(&sub_account, 1_000_000_000)?; // 1 SOL

    // Create a transfer from the sub account
    let recipient = Keypair::new().pubkey();
    let transfer_amount = 100_000_000; // 0.1 SOL

    // Create the transfer instruction targeting the subaccount
    // The subaccount address is used as the 'from' account
    let transfer_ix = system_instruction::transfer(
        &sub_account,      // from: subaccount address
        &recipient,        // to: recipient
        transfer_amount,   // amount
    );

    // Sign with sub account using the SwigInstructionBuilder
    // Note: The builder should be configured with the sub_account_authority
    // and the appropriate role_id that has subaccount permissions
    let mut sub_account_builder = SwigInstructionBuilder::new(
        swig_id,
        Box::new(Ed25519ClientRole::new(sub_account_authority.pubkey())),
        fee_payer.pubkey(),
        sub_account_role_id,
    );

    // Sign the instruction for subaccount use
    // The sign_instruction method will handle subaccount signing when the role
    // has subaccount permissions and the instruction targets the subaccount address
    let signed_instructions = sub_account_builder.sign_instruction(
        vec![transfer_ix],
        None, // current_slot not required for Ed25519
    )?;

    // Build and send the transaction
    let recent_blockhash = rpc_client.get_latest_blockhash()?;
    let msg = v0::Message::try_compile(
        &fee_payer.pubkey(),
        &signed_instructions,
        &[],
        recent_blockhash,
    )?;

    let tx = VersionedTransaction::try_new(
        VersionedMessage::V0(msg),
        &[fee_payer, &sub_account_authority],
    )?;

    rpc_client.send_and_confirm_transaction(&tx)?;
    ```
  </Tab>
</Tabs>

## Key Features of Sub Accounts

Sub accounts in Swig have several important characteristics:

* **Dedicated Addresses**: Each sub account has its own unique address derived from the Swig ID, role ID, and index
* **Multiple Per Role**: Each role can have up to 255 subaccounts (indices 0-254), enabling parallel operations
* **Isolated Operations**: Sub accounts can perform complex operations without affecting the main Swig balance
* **Backwards Compatible**: Index 0 maintains the same address derivation as v1.3.x for seamless upgrades
* **Root Authority Control**: The root authority can always reclaim funds from sub accounts
* **Permission-Based**: Only authorities with sub account permissions can create and manage sub accounts
* **Unlimited Actions**: Sub accounts can perform any on-chain action within their permission scope
* **Index-Specific Permissions**: Each subaccount index requires its own SubAccount action/permission

## Testing Environment Options

These examples can be run in different environments:

* **Local Validator**: Use the examples above
  * Requires running a local Solana validator with `bun start-validator`
  * Real blockchain environment
  * Good for final testing

* **LiteSVM**: For rapid development and testing
  * No validator required
  * Instant transaction confirmation
  * Perfect for rapid development
  * Simulates the Solana runtime

* **Devnet**: All examples work with devnet
  * Change connection URL to `https://api.devnet.solana.com`
  * Real network environment
  * Free to use with airdropped SOL

<Tabs>
  <Tab title="Classic">
    ```typescript theme={null}
    // Local validator
    const connection = new Connection('http://localhost:8899', 'confirmed');

    // Devnet
    const connection = new Connection('https://api.devnet.solana.com', 'confirmed');
    ```
  </Tab>

  <Tab title="Kit">
    ```typescript theme={null}
    // Local validator
    const connection = {
      rpc: createSolanaRpc('http://localhost:8899'),
      rpcSubscriptions: createSolanaRpcSubscriptions('ws://localhost:8900'),
    };

    // Devnet
    const connection = {
      rpc: createSolanaRpc('https://api.devnet.solana.com'),
      rpcSubscriptions: createSolanaRpcSubscriptions('wss://api.devnet.solana.com'),
    };
    ```
  </Tab>
</Tabs>

## Use Cases

Sub accounts are perfect for:

* **Portfolio Management**: Allow complex DeFi operations without full wallet access
* **Yield Optimization**: Automated strategies with isolated risk
* **Multi-Strategy Trading**: Separate subaccounts for different trading strategies (now with multiple per role!)
* **Asset Segregation**: Different subaccounts for different asset classes or risk profiles
* **Custodial Services**: Per-client subaccounts with a single authority managing multiple clients
* **Parallel Operations**: Execute independent operations simultaneously across different subaccounts
* **Delegation**: Give specific permissions for particular use cases

## Additional Resources

You can find more working examples in our repositories:

* **Rust Examples**: [Swig test suite](https://github.com/anagrambuild/swig-wallet/blob/main/program/tests/sub_account_test.rs#L33)
* **Classic TypeScript (Single)**: [transfer-svm-subaccount.ts](https://github.com/anagrambuild/swig-ts/blob/main/examples/classic/transfer/transfer-svm-subaccount.ts)
* **Kit TypeScript (Single)**: [transfer-local-subaccount.ts](https://github.com/anagrambuild/swig-ts/blob/main/examples/kit/transfer/transfer-local-subaccount.ts)
* **Classic TypeScript (Multiple)**: [multi-subaccount-svm.ts](https://github.com/anagrambuild/swig-ts/blob/main/examples/classic/transfer/multi-subaccount-svm.ts)
* **Kit TypeScript (Multiple)**: [multi-subaccount-local.ts](https://github.com/anagrambuild/swig-ts/blob/main/examples/kit/transfer/multi-subaccount-local.ts)
* **All Examples**: [Swig TypeScript examples](https://github.com/anagrambuild/swig-ts/tree/main/examples)

## Migration Guide

If you're upgrading from v1.3.x to v1.4.x, your existing subaccounts will continue to work without any changes. The default subaccount (index 0) uses the same address derivation as before, ensuring backwards compatibility. To take advantage of multiple subaccounts, simply add additional `SubAccount` actions with different indices to your roles.
