In this tutorial, we’ll learn how to add multiple authorities to a Swig account with different permission sets. We’ll create a root authority that can manage other authorities, then add two specialized authorities: one for SOL spending and another for token management.
Prerequisites
Before starting this tutorial:
- Make sure you’re in the
examples/transfer/tutorial
directory
- Ensure your local validator is running with:
Quick Review
In Tutorial 1, we learned how to create a basic Swig account. Now we’ll expand on that by managing multiple authorities with different permissions.
mkdir tutorial && touch tutorial-2.ts
Open that file up in your favorite editor, or AI overlord super virtual reality googles. Lets make a function called createSwigAccount
Example(note this is only the changed code)
async function addNewAuthority(
connection: Connection,
rootUser: Keypair,
newAuthority: Keypair,
swigAddress: PublicKey,
actions: any,
description: string
) {
try {
// Fetch the Swig account
const swig = await fetchSwig(connection, swigAddress);
// Find the root role that can manage authorities
const rootRole = swig.findRolesByEd25519SignerPk(rootUser.publicKey)[0];
if (!rootRole) {
throw new Error('Root role not found for authority');
}
// Create the instruction to add the new authority
const addAuthorityIx = await addAuthorityInstruction(
rootRole,
rootUser.publicKey,
createEd25519AuthorityInfo(newAuthority.publicKey),
actions,
);
// Send and confirm the transaction
const transaction = new Transaction().add(addAuthorityIx);
await sendAndConfirmTransaction(connection, transaction, [rootUser]);
console.log(chalk.green(`✓ New ${description} authority added:`), chalk.cyan(newAuthority.publicKey.toBase58()));
} catch (error) {
console.error(chalk.red(`✗ Error adding ${description} authority:`), chalk.red(error));
throw error;
}
}
(async () => {
console.log(chalk.blue("🚀 Starting tutorial - Adding Multiple Authorities"));
// Connect to local Solana network
const connection = new Connection('http://localhost:8899', 'confirmed');
// Create and fund the root user
const rootUser = Keypair.generate();
console.log(chalk.green("👤 Root user public key:"), chalk.cyan(rootUser.publicKey.toBase58()));
let airdrop = await connection.requestAirdrop(rootUser.publicKey, 100 * LAMPORTS_PER_SOL);
let blockhash = await connection.getLatestBlockhash();
await connection.confirmTransaction({
signature: airdrop,
blockhash: blockhash.blockhash,
lastValidBlockHeight: blockhash.lastValidBlockHeight,
});
// Create the Swig account
console.log(chalk.yellow("\n📝 Creating Swig account..."));
const swigAddress = await createSwigAccount(connection, rootUser);
// Create the spending authority
const spendingAuthority = Keypair.generate();
console.log(chalk.green("\n👥 Spending authority public key:"), chalk.cyan(spendingAuthority.publicKey.toBase58()));
// Create the token authority
const tokenAuthority = Keypair.generate();
console.log(chalk.green("👥 Token authority public key:"), chalk.cyan(tokenAuthority.publicKey.toBase58()));
// Add some delay to ensure the Swig account is created
await new Promise(resolve => setTimeout(resolve, 2000));
// Add spending authority with SOL limit
console.log(chalk.yellow("\n🔑 Adding spending authority..."));
const spendingActions = Actions.set()
.solLimit({ amount: BigInt(0.1 * LAMPORTS_PER_SOL) })
.get();
await addNewAuthority(connection, rootUser, spendingAuthority, swigAddress, spendingActions, "spending");
// Add token authority with token management permissions
console.log(chalk.yellow("\n🔑 Adding token authority..."));
const tokenMint = Keypair.generate().publicKey; // Example token mint
const tokenActions = Actions.set()
.tokenLimit({ mint: tokenMint, amount: BigInt(1000000) })
.get();
await addNewAuthority(connection, rootUser, tokenAuthority, swigAddress, tokenActions, "token");
// Verify the authorities were added
const swig = await fetchSwig(connection, swigAddress);
console.log(chalk.blue("\n📊 Authority Permissions:"));
const spendingRole = swig.findRolesByEd25519SignerPk(spendingAuthority.publicKey)[0];
console.log(chalk.yellow("Spending Authority:"));
console.log("- Can spend SOL:", chalk.green(spendingRole.canSpendSol(BigInt(0.1 * LAMPORTS_PER_SOL))));
console.log("- Can spend tokens:", chalk.red(spendingRole.canSpendToken(tokenMint, BigInt(1000000))));
const tokenRole = swig.findRolesByEd25519SignerPk(tokenAuthority.publicKey)[0];
console.log(chalk.yellow("\nToken Authority:"));
console.log("- Can spend SOL:", chalk.red(tokenRole.canSpendSol(BigInt(0.1 * LAMPORTS_PER_SOL))));
console.log("- Can spend tokens:", chalk.green(tokenRole.canSpendToken(tokenMint, BigInt(1000000))));
await new Promise(resolve => setTimeout(resolve, 2000));
console.log(chalk.green("\n✨ Tutorial completed successfully!"));
console.log(chalk.yellow("🔍 Check out your transaction on Solana Explorer:"));
console.log(chalk.cyan(`https://explorer.solana.com/address/${swigAddress}?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899`));
})();
Code Breakdown
Let’s examine the key parts of tutorial-2.ts
:
1. Creating a Root Authority
const rootActions = Actions.set().manageAuthority().get();
const tx = await createSwig(
connection,
id,
rootAuthority,
rootActions,
user.publicKey,
[user]
);
This creates a Swig account where the root authority has permission to manage other authorities. We specifically use .manageAuthority()
to limit this authority to only managing other authorities.
2. Adding a SOL Spending Authority
Dont forget that the full list of actions an authority can have is here.
const spendingActions = Actions.set()
.solLimit({ amount: BigInt(0.1 * LAMPORTS_PER_SOL) })
.get();
await addNewAuthority(
connection,
rootUser,
spendingAuthority,
swigAddress,
spendingActions,
"spending"
);
This creates an authority that:
- Can only spend SOL (no token permissions)
- Has a spending limit of 0.1 SOL
- Cannot manage other authorities
3. Adding a Token Authority
const tokenMint = Keypair.generate().publicKey; // Example token mint
const tokenActions = Actions.set()
.tokenLimit({ mint: tokenMint, amount: BigInt(1000000) })
.get();
await addNewAuthority(
connection,
rootUser,
tokenAuthority,
swigAddress,
tokenActions,
"token"
);
This creates an authority that:
- Can only manage tokens for a specific mint
- Has a token spending limit of 1,000,000 units
- Cannot spend SOL or manage other authorities
Understanding the Output
When you run the tutorial, you’ll see:
- The root user’s public key
- The Swig account address
- Two new authority public keys
- A permission summary showing what each authority can and cannot do
The tutorial provides links to view your transactions on Solana Explorer (using your local validator).
Key Concepts
- Root Authority: An authority with management permissions that can add or remove other authorities
- Specialized Authorities: Authorities with specific, limited permissions (e.g., SOL spending or token management)
- Permission Limits:
- SOL limits are set in lamports (1 SOL = 1,000,000,000 lamports)
- Token limits are set based on the token’s decimals
- Action Sets: Define what an authority can do using methods like:
.manageAuthority()
.solLimit()
.tokenLimit()
Running the Tutorial
Execute the tutorial with:
You nailed it , first try!! You now have a multi authority Swig, free energy and perpetual motion next.