Claim tokens
Token Claim Process
Claiming tokens requires proof of eligibility and proper setup of the recipient's token account. This is a two-phase operation:
- Prepare the claimant's token account
- Verify and execute the claim
1. Generate Merkle Proof
import { getMerkleProof } from "./merkleUtils";
// Get proof for specific claim (must match original claim list)
const claimProof = getMerkleProof(
merkleTree,
claimer.address,
claimAmount,
claimIndex
);
Create the cryptographic proof of eligibility
2. Find Claimant's Token Account
import {findAssociatedTokenPda, TOKEN_PROGRAM_ADDRESS } from "@solana-program/token";
const [destinationTokenAccount] = await findAssociatedTokenPda({
owner: claimer.address,
mint: mint, //mint address
tokenProgram: TOKEN_PROGRAM_ADDRESS, // or TOKEN_2022
});
Locate or create the destination for claimed tokens
3. Create Claimant's ATA (If Needed)
import { getCreateAssociatedTokenIdempotentInstructionAsync } from "@solana-program/token";
const destinationATACreateIx = await getCreateAssociatedTokenIdempotentInstructionAsync({
ata: destinationTokenAccount,
mint: mint,
payer: claimer,
owner: claimer.address,
});
Idempotent account creation
4. Get Claim Instruction
import { getClaimTokensInstruction } from "@dropsy/airdrop";
const instruction = getClaimTokensInstruction({
vault: vault, // Airdrop's token vault
destinationTokenAccount, // Claimant's ATA
airdrop: airdropPda, // Airdrop address
bitmap: claimMap, // Claim tracking account
mint: mint, // Token mint
claimer: claimer, // Claimant's wallet (signer)
tokenProgram: TOKEN_PROGRAM_ADDRESS, // or TOKEN_2022
index: claimIndex, // Must match original list
amount: claimAmount, // Must match original list
proof: claimProof // Generated Merkle proof
});
Create the instruction to verify and transfer tokens
5. Build Claim Transaction
const transactionMessage = await createTransactionMessageFromInstructions(
client.rpc,
claimer, //signer
[destinationATACreateIx, instruction] // order matters if you decide to implement a transaction for each instruction
);
const signedTransaction = await signTransactionMessageWithSigners(
transactionMessage
);
Build a Transaction from both instructions and Sign it
6. 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.
Critical Requirements
- Exact Match: Index, amount, and address must exactly match original claim list
- Claim Window: Must be within starts_at and ends_at period
- One-Time Claim: Bitmap prevents duplicate claims