Approve and Revoke Instructions
Approve grants a delegate the authority to transfer a specific amount of tokens on behalf of the account owner. This enables programmatic token transfers without giving full account control.
We set an "approved" amount, and the delegate can transfer only up to that amount
Revoke removes the current delegate's authority over the account, returning full control to the account owner.
Immediately cancels any existing delegation and only the account owner can revoke delegation (not the delegate itself)
Before we can mint any token, we'll need to already have:
- Initialized a
Mint
account which we hold themintAuthority
- Initialized a
Token
account orAssociated Token
account where we're going to take control of
The amount of tokens we mint are "normalized" for decimals. This means that if we want to mint 1 token that has 6 decimals, we'll need to actually put
1e6
as amount
Raw Instruction
By using just "raw" instruction without any abstraction, this is how approve a token would look like:
const tokenAccount = Keypair.generate();
const tokenAccount = await getAssociatedTokenAddress(
mint.publicKey,
tokenAccount.publicKey,
);
// Create ATA creation instruction
const createAtaInstruction = createAssociatedTokenAccountIdempotentInstruction(
keypair.publicKey, // payer
tokenAccount, // associated token account address
destination.publicKey, // owner
mint.publicKey, // mint
);
// Delegate an ATA
const approveInstruction = createApproveInstruction(
tokenAccount // account
delegate.publicKey, // delegate
keypair.publickey // owner
1e6, // amount of tokens
);
const transaction = new Transaction().add(
createAtaInstruction,
approveInstruction,
);
const signature = await sendAndConfirmTransaction(connection, transaction, [keypair]);
console.log(`Token accounts created and delegated! Check out your TX here: https://explorer.solana.com/tx/${signature}?cluster=devnet`);
By using just "raw" instruction without any abstraction, this is how revoke a token would look like:
// Revoke the delegate of an ATA
const revokeInstruction = createRevokeInstruction(
tokenAccount // account
keypair.publickey // owner
);
const transaction = new Transaction().add(revokeInstruction);
const signature = await sendAndConfirmTransaction(connection, transaction, [keypair]);
console.log(`Token account delegate revoked! Check out your TX here: https://explorer.solana.com/tx/${signature}?cluster=devnet`);
Abstracted Instruction
This is how the same instructions would look like abstracted away with the approve()
instruction:
const tokenAccount = Keypair.generate();
const ata = await getOrCreateAssociatedTokenAccount(
connection,
keypair,
mint,
tokenAccount.publicKey
);
console.log(`This is your ATA: ${ata.address}!`)
let tx = await approve(
connection,
keypair,
ata.address, // token Account
delegate-publicKey, // delegate
keypair.publicKey, // owner
1e6, // amount
);
console.log(`Succesfully Delegated!. Transaction Here: https://explorer.solana.com/tx/${tx}?cluster=devnet`)
This is how the same instructions would look like abstracted away with the revoke()
instruction:
let tx = await revoke(
connection,
keypair,
ata.address, // token Account
keypair.publicKey, // owner
);
console.log(`Succesfully Revoked Delegate!. Transaction Here: https://explorer.solana.com/tx/${tx}?cluster=devnet`)