Approve and Revoke Delegate Authority
Complete guide to manage delegate authority for compressed tokens with `approve()` and `revoke()`, troubleshooting and advanced configurations.
The approve() and revoke() functions grant and remove delegate spending authority for compressed tokens. Only the token owner can perform these operations.
Before we approve or revoke delegates, we need:
compressed token accounts to delegate or revoke delegation from, and
an SPL mint with a token pool for compression. This token pool can be created for new SPL mints via
createMint()or added to existing SPL mints viacreateTokenPool().
// Approve delegate for spending up to the specified amount
const approveSignature = await approve(
rpc,
payer,
mint, // SPL mint with token pool for compression
amount,
owner,
delegate.publicKey, // delegate account
);// Get delegated accounts for revocation
const delegatedAccounts = await rpc.getCompressedTokenAccountsByDelegate(
delegate.publicKey,
{ mint }
);
// Revoke delegate authority
const revokeSignature = await revoke(
rpc,
payer,
delegatedAccounts.items, // delegated compressed token accounts
owner,
);Full Code Example
Approve / Revoke Delegates
Approve delegate authority for compressed tokens. The delegate can spend up to the approved amount.
// 1. Setup funded payer and connect to local validator
// 2. Create mint and token pool with initial tokens
// 3. Call approve() with mint, amount, owner, delegate
// 4. Verify delegation via getCompressedTokenAccountsByDelegate
import { Keypair } from '@solana/web3.js';
import { createRpc } from '@lightprotocol/stateless.js';
import {
createMint,
mintTo,
approve
} from '@lightprotocol/compressed-token';
import BN from 'bn.js';
async function approveDelegates() {
// Step 1: Setup funded payer and connect to local validator
const rpc = createRpc(); // defaults to localhost:8899
const payer = Keypair.generate();
const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); // 1 SOL
await rpc.confirmTransaction(airdropSignature);
// Step 2: Create SPL mint with token pool and mint initial tokens
const { mint } = await createMint(
rpc,
payer,
payer.publicKey, // mint authority
9 // decimals
);
console.log("SPL mint with token pool created:", mint.toBase58());
const tokenOwner = Keypair.generate();
const initialAmount = 1_000_000_000; // 1 token with 9 decimals
await mintTo(
rpc,
payer,
mint, // SPL mint with token pool for compression
tokenOwner.publicKey, // recipient
payer, // mint authority
initialAmount
);
console.log("Initial tokens minted:", initialAmount / 1_000_000_000, "tokens");
console.log("Token owner:", tokenOwner.publicKey.toBase58());
// Generate delegate address and define amount to approve for delegation
const delegate = Keypair.generate();
const delegateAmount = 500_000_000; // 0.5 tokens
// Step 3: Call approve() with mint, amount, owner, delegate
const approveTx = await approve(
rpc,
payer,
mint, // SPL mint with token pool for compression
delegateAmount,
tokenOwner, // owner keypair
delegate.publicKey // delegate address
);
console.log("Delegate approved");
console.log("Delegate:", delegate.publicKey.toBase58());
console.log("Approved amount:", delegateAmount / 1_000_000_000, "tokens");
console.log("Transaction:", approveTx);
// Step 4: Verify delegation via getCompressedTokenAccountsByDelegate
const delegateAccounts = await rpc.getCompressedTokenAccountsByDelegate(
delegate.publicKey,
{ mint }
);
// Check delegated balance
if (delegateAccounts.items.length > 0) {
const delegatedBalance = delegateAccounts.items.reduce(
(sum, account) => sum.add(account.parsed.amount),
new BN(0)
);
console.log("Verified delegation:", delegatedBalance.toNumber() / 1_000_000_000, "tokens");
}
return {
mint,
tokenOwner,
delegate: delegate.publicKey,
approveTransaction: approveTx,
delegatedAmount: delegateAmount
};
}
approveDelegates().catch(console.error);Approve delegation, then revoke it in a single script.
// Complete workflow: approve and revoke delegation
// 1. Setup and create mint with initial tokens
// 2. Approve delegation
// 3. Verify delegation exists
// 4. Revoke delegation
// 5. Verify delegation removed
import { Keypair } from '@solana/web3.js';
import { createRpc } from '@lightprotocol/stateless.js';
import {
createMint,
mintTo,
approve,
revoke
} from '@lightprotocol/compressed-token';
import BN from 'bn.js';
async function approveAndRevokeDelegates() {
// Step 1: Setup funded payer and connect to local validator
const rpc = createRpc(); // defaults to localhost:8899
const payer = Keypair.generate();
const airdropSignature = await rpc.requestAirdrop(payer.publicKey, 1000000000); // 1 SOL
await rpc.confirmTransaction(airdropSignature);
// Create SPL mint with token pool and mint initial tokens
const { mint } = await createMint(
rpc,
payer,
payer.publicKey, // mint authority
9 // decimals
);
console.log("SPL mint with token pool created:", mint.toBase58());
const tokenOwner = Keypair.generate();
const initialAmount = 1_000_000_000; // 1 token with 9 decimals
await mintTo(
rpc,
payer,
mint, // SPL mint with token pool for compression
tokenOwner.publicKey, // recipient
payer, // mint authority
initialAmount
);
console.log("Initial tokens minted:", initialAmount / 1_000_000_000, "tokens");
console.log("Token owner:", tokenOwner.publicKey.toBase58());
// Generate delegate and define delegation amount
const delegate = Keypair.generate();
const delegateAmount = 500_000_000; // 0.5 tokens
// Step 2: Approve delegation
console.log("\n--- Approving Delegation ---");
const approveTx = await approve(
rpc,
payer,
mint,
delegateAmount,
tokenOwner,
delegate.publicKey
);
console.log("Delegate approved");
console.log("Delegate:", delegate.publicKey.toBase58());
console.log("Approved amount:", delegateAmount / 1_000_000_000, "tokens");
console.log("Transaction:", approveTx);
// Step 3: Verify delegation exists
const delegateAccountsBefore = await rpc.getCompressedTokenAccountsByDelegate(
delegate.publicKey,
{ mint }
);
const delegatedBalance = delegateAccountsBefore.items.reduce(
(sum, account) => sum.add(account.parsed.amount),
new BN(0)
);
console.log("Verified delegation:", delegatedBalance.toNumber() / 1_000_000_000, "tokens");
// Step 4: Revoke delegation
console.log("\n--- Revoking Delegation ---");
const revokeTx = await revoke(
rpc,
payer,
delegateAccountsBefore.items, // delegated accounts to revoke
tokenOwner,
);
console.log("Delegate revoked!");
console.log("Transaction:", revokeTx);
// Step 5: Verify delegation removed
const delegateAccountsAfter = await rpc.getCompressedTokenAccountsByDelegate(
delegate.publicKey,
{ mint }
);
const ownerAccounts = await rpc.getCompressedTokenAccountsByOwner(
tokenOwner.publicKey,
{ mint }
);
const ownerBalance = ownerAccounts.items.reduce(
(sum, account) => sum.add(account.parsed.amount),
new BN(0)
);
console.log("\n--- Final State ---");
console.log("Delegated accounts remaining:", delegateAccountsAfter.items.length);
console.log("Owner balance after revocation:", ownerBalance.toNumber() / 1_000_000_000, "tokens");
return {
approveTransaction: approveTx,
revokeTransaction: revokeTx,
finalOwnerBalance: ownerBalance
};
}
approveAndRevokeDelegates().catch(console.error);Troubleshooting
Advanced Configuration
Next Steps
That's it! Explore more guides in our cookbook section, or check out the advanced guides.
Last updated
Was this helpful?