import {
Connection,
Keypair,
SystemProgram,
Transaction,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import {
ExtensionType,
TOKEN_2022_PROGRAM_ID,
createInitializeMintInstruction,
createInitializeTransferFeeConfigInstruction,
getMintLen,
createMintToInstruction,
createAssociatedTokenAccountInstruction,
getAssociatedTokenAddressSync,
} from "@solana/spl-token";
import {
createInitializeInstruction,
createInitializeMetadataPointerInstruction,
pack,
TokenMetadata,
TYPE_SIZE,
LENGTH_SIZE,
} from "@solana/spl-token-metadata";
import bs58 from "bs58";
import "dotenv/config";
const connection = new Connection(process.env.SOLANA_RPC!);
const payer = Keypair.fromSecretKey(bs58.decode(process.env.PRIVATE_KEY!));
const mintKeypair = Keypair.generate();
const mint = mintKeypair.publicKey;
const decimals = 6;
const transferFeeBasisPoints = 100; // 1%
const maxFee = BigInt(1_000_000); // 1 token max fee
// Metadata for the token
const metadata: TokenMetadata = {
mint: mint,
name: "My Hackathon Token",
symbol: "HACK",
uri: "https://example.com/metadata.json",
additionalMetadata: [],
};
async function createTokenWithExtensions() {
// Calculate space needed for mint + extensions
const extensions = [ExtensionType.TransferFeeConfig, ExtensionType.MetadataPointer];
const mintLen = getMintLen(extensions);
const metadataLen = TYPE_SIZE + LENGTH_SIZE + pack(metadata).length;
const totalLen = mintLen + metadataLen;
const lamports = await connection.getMinimumBalanceForRentExemption(totalLen);
const transaction = new Transaction().add(
// Create account
SystemProgram.createAccount({
fromPubkey: payer.publicKey,
newAccountPubkey: mint,
space: mintLen,
lamports,
programId: TOKEN_2022_PROGRAM_ID,
}),
// Initialize metadata pointer (points to the mint itself)
createInitializeMetadataPointerInstruction(
mint,
payer.publicKey, // metadata pointer authority
mint, // metadata account (self-referencing)
TOKEN_2022_PROGRAM_ID
),
// Initialize transfer fee extension
createInitializeTransferFeeConfigInstruction(
mint,
payer.publicKey, // transfer fee config authority
payer.publicKey, // withdraw withheld authority
transferFeeBasisPoints,
maxFee,
TOKEN_2022_PROGRAM_ID
),
// Initialize mint
createInitializeMintInstruction(
mint,
decimals,
payer.publicKey,
null, // no freeze authority
TOKEN_2022_PROGRAM_ID
),
// Initialize on-chain metadata
createInitializeInstruction({
programId: TOKEN_2022_PROGRAM_ID,
mint: mint,
metadata: mint, // metadata stored on the mint itself
name: metadata.name,
symbol: metadata.symbol,
uri: metadata.uri,
mintAuthority: payer.publicKey,
updateAuthority: payer.publicKey,
})
);
const sig = await sendAndConfirmTransaction(connection, transaction, [
payer,
mintKeypair,
]);
console.log("Token created:", mint.toBase58());
console.log("Transaction:", sig);
}
createTokenWithExtensions();