Initialize Controller
Now that you understand the Controller's structure and purpose, let's create one on-chain. This process will establish your authority root for managing airdrops and fee collection.
Step-by-Step Breakdown
1. PDA Derivation
const [controllerPda] = await getControllerDerivedAddress(wallet.address);
Uses the same deterministic derivation covered earlier, ensuring consistent address generation.
2. Instruction Creation
const instruction = await getInitializeControllerInstructionAsync({
authority: client.wallet, // The signer and authority
feeLamports: BigInt(5000), // Customize your fee amount
});
// Derive the feeVault address (a PDA seeded with the controller)
const [feeVault, feeVaultBump] = await getControllerVaultAddress(controllerPda);
This instruction prepares all necessary metadata for initializing the controller on-chain, including the creation of the feeVault
— a Program Derived Address (PDA) used to hold controller fees.
3. Transaction Building and Signing
const transactionMessage = await createTransactionMessageFromInstructions(
client.rpc,
client.wallet,
[instruction]
);
const signedTransaction = await signTransactionMessageWithSigners(
transactionMessage
);
Prepares the transaction for network transmission and signs it with the wallet.
4. Send and Confirm Transaction
await client.sendAndConfirmTransaction(signedTransaction, { commitment: "confirmed" });
const signature = getSignatureFromTransaction(signedTransaction);
console.log("signature:", signature);
Submits the signed transaction to the network and waits for confirmation.
✅ After confirmation, your Controller is active and ready to manage airdrops!
Complete Initialization Example
import { getControllerDerivedAddress, getInitializeControllerInstructionAsync } from "@dropsy/airdrop";
import { getSignatureFromTransaction, signTransactionMessageWithSigners } from "@solana/kit";
import { createClient } from "./client";
import { createTransactionMessageFromInstructions } from "./utils";
async function initializeController() {
const client = await createClient();
const [controllerPda, bump] = await getControllerDerivedAddress(client.wallet.address);
const instruction = await getInitializeControllerInstructionAsync({
authority: client.wallet,
controller: controllerPda,
feeLamports: BigInt(5000),
});
const transactionMessage = await createTransactionMessageFromInstructions(
client.rpc,
client.wallet,
[instruction],
);
const signedTransaction = await signTransactionMessageWithSigners(
transactionMessage
);
await client.sendAndConfirmTransaction(signedTransaction, { commitment: "confirmed" });
const signature = getSignatureFromTransaction(signedTransaction);
console.log("signature : ", signature)
console.log('your controller address : ', controllerPda)
}
Key Details:
- Fee Structure: The specified fee (5000 lamports) will be charged per airdrop operation
- Atomic Operation: Creates both Controller and associated fee vault in one transaction
- Gas Costs: Expect ~0.002 SOL for account initialization (rent-exempt minimum)