Before we begin our quest lets make sure you have the basics ready so lets set up a basic project, if you have already done this, feel free to move on. If you have not finished step 0 in this tutorial please go back and run through that as we refer back and depend on this step.

Now that you have your environment all setup and ready to role, make a new file called tutorial.ts, make sure you are in the examples/transfer folder. Don’t forget to start your validator with bun start-validator

mkdir tutorial && touch tutorial-1.ts

Open that file up in your favorite editor, or AI overlord super virtual reality googles. Lets make a function called createSwigAccount

Example

import {
  Keypair,
  LAMPORTS_PER_SOL,
  Connection,
} from '@solana/web3.js';

import {
  Actions,
  createSwig,
  Ed25519Authority,
  findSwigPda
} from "@swig-wallet/classic";

import chalk from 'chalk';

async function createSwigAccount(
  connection: Connection,
  user: Keypair,
) {
  try {
    const id = new Uint8Array(32);
    crypto.getRandomValues(id);
    const [swigAddress] = findSwigPda(id);
    const rootAuthority = Ed25519Authority.fromPublicKey(user.publicKey);
    const rootActions = Actions.set().manageAuthority().get();
    const tx = await createSwig(
      connection,
      id,
      rootAuthority,
      rootActions,
      user.publicKey,
      [user]
    );

    console.log(chalk.green("✓ Swig account created at:"), chalk.cyan(swigAddress.toBase58()));
    return swigAddress;
  } catch (error) {
    console.error(chalk.red("✗ Error creating Swig account:"), chalk.red(error));
    throw error;
  }
}

(async () => {
  console.log(chalk.blue("🚀 Starting tutorial"));
  const connection = new Connection('http://localhost:8899', 'confirmed');
  const userKeypair = Keypair.generate();
  let f = await connection.requestAirdrop(userKeypair.publicKey, 100 * LAMPORTS_PER_SOL);
  let blockhash = await connection.getLatestBlockhash();
  await connection.confirmTransaction({
    signature: f,
    blockhash: blockhash.blockhash,
    lastValidBlockHeight: blockhash.lastValidBlockHeight,
  })
  console.log(chalk.green("👤 User public key:"), chalk.cyan(userKeypair.publicKey.toBase58()));
  let swigAddress = await createSwigAccount(connection, userKeypair);
  await setTimeout(() => {
    console.log(chalk.green("\n✨ Everything looks good!"));
    console.log(chalk.yellow("🔍 Check out your transaction on Solana Explorer:"));
    console.log(chalk.cyan(`https://explorer.solana.com/address/${swigAddress.toBase58()}?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899`));
  }, 2000);
})();

Lets save this and get ready to run it, but before we do lets break it down step by step.

1. Import Required SDKs

import { Connection, PublicKey, LAMPORTS_PER_SOL } from "@solana/web3.js";
import { 
  Actions, 
  createSwig, 
  Ed25519Authority, 
  findSwigPda 
} from "@swig-wallet/classic";

Imports Solana primitives and essential utilities from the Swig SDK.

2. Generate a Unique Swig ID

//in the create swig function
const id = new Uint8Array(32);
crypto.getRandomValues(id);

Generates a secure 32-byte ID that uniquely identifies this Swig wallet instance. This ID is used to derive the PDA (Program Derived Address).

💡 This can really be anything, as long as it’s globally unique. You can even use other public keys, strings, or a boring old number if needed.

3. Derive the Swig PDA

const [swigAddress] = findSwigPda(id);

Computes the wallet’s on-chain PDA using the generated ID. This is the unique address of the Swig account on Solana.

🧠 This is a standard Solana pattern—Swig just makes it easier.

4. Create the Root Role

Swig is role-based: it combines Authorities (who) and Actions (what) to determine permissions. This section builds the root role.

const rootAuthority = Ed25519Authority.fromPublicKey(user.publicKey);
const rootActions = Actions.set().manageAuthority().get();

This sets up the root role. Since this is the root, it must have at least manageAuthority() or all().

manageAuthority() is restrictive but safe.

🚨 all() gives full control—use carefully in production.

You can find all available action types in the Swig SDK docs. New types may be added over time.

Swig supports multiple Authority types—this example uses Ed25519Authority, but others are available for different credentials or verification methods. These handle the Authentication half of Swig’s model. You can find all the types of authorities on the SDK Docs.

5. Create the Swig Account On-Chain

const tx = await createSwig(
  connection,
  id,
  rootAuthority,
  rootActions,
  user.publicKey,
  [user]
);

Creates the Swig account by sending a transaction to the Solana blockchain. The transaction must be signed by the user. In this case the payer of the transaction and the rent is the user, but you can also have a different fee payer for transaction for an example see this.

6. Simulate a Funded User

const userKeypair = Keypair.generate();
let f = await connection.requestAirdrop(userKeypair.publicKey, 100 * LAMPORTS_PER_SOL);
let blockhash = await connection.getLatestBlockhash();
await connection.confirmTransaction({
  signature: f,
  blockhash: blockhash.blockhash,
  lastValidBlockHeight: blockhash.lastValidBlockHeight,
});

Creates a fresh Keypair and airdrops some SOL from the local validator so it can pay for the transaction.

7. Connect to the Validator

const connection = new Connection('http://localhost:8899', 'confirmed');

Creates a connection to the local Solana cluster. Ensure you’ve run:

//in the transfer folder
bun start-validator

This spins up a local testnet with the Swig programs deployed.

8. Log Success

console.log(chalk.green("✓ Swig account created at:"), chalk.cyan(swigAddress.toBase58()));

Prints the address of the new Swig account in a colorized format.

Ready to run it?

bun run ./tutorial-1.ts

Congratulations on your first Swig!