It's Friday night, everyone's hyped, and boom-you're the Solana wizard who makes it happen in under 30 minutes. Sound familiar? That's SPL tokens for ya. Super cheap, like 0.000005 SOL per tx kinda cheap, and stupid fast. No code if you don't want it. I did this last week for a joke token called "PizzaSlice"-minted 1 million, added a dumb pizza pic, and it was live on Phantom wallets before my coffee got cold.
The thing is, Solana's SPL standard is basically magic for creating fungible tokens. Think USDC or your own community coin. Why bother? Fees are nothing compared to Ethereum's gas wars, and it scales like crazy. But don't just YOLO into mainnet. We'll start on devnet, where SOL is free.
Grab a terminal. Mac, Linux, Windows with WSL-doesn't matter. I usually skip the fancy IDEs at first.
sh -c "$(curl -sSfL https://release.solana.com/stable/install)". Then solana --version to check. Boom, done.curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh. Restart terminal after.cargo install spl token cli. This is your token Swiss Army knife.What's next? Wallet time. Run solana keygen new --outfile ~/my sol wallet.json. It'll spit out a seed phrase-write it down, idiot proof it on paper. Set it default: solana config set --keypair ~/my sol wallet.json.
Fund it free on devnet: solana config set --url https://api.devnet.solana.com then solana airdrop 2. You'll get 2 SOL. If it flakes (rate limits suck), wait 30 secs or hit it again. In my experience, third time's the charm.
Switch to Phantom or Solflare for testing later. Connect to devnet there too. Hardware wallet? Pair it with Ledger for mainnet deploys-keeps keys offline.
Token mint is the master account controlling supply. Run spl token create token. It'll output something like Creating token 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg. Copy that TOKEN_ADDRESS. That's your baby's ID. Costs like 0.002 SOL rent, refunded if you close later.
Why does this matter? This address is eternal on the blockchain. Share it, and anyone can interact with your token.
Short sentence. Exciting, right?
Wallets don't hold tokens directly. Need a token account linked to your wallet and this mint.
spl token create account TOKEN_ADDRESS. Uses Associated Token Account (ATA)-auto derives from your wallet + mint. Smart, huh?spl token accounts. See your balance at 0.If you're giving tokens to someone else, spl token create account --owner THEIRWALLET TOKENADDRESS. But for now, yours.
Common snag? "Account already exists." That's good-means ATA is set. Potential issue: insufficient SOL. Airdrop more.
Mint means create new tokens. You're the mint authority by default.
spl token mint TOKENADDRESS 1000000 Whoa, 1 million tokens in your account. Decimals? SPL defaults to 9, like SOL-so 1000000 is 1 whole token if you set decimals later, but basic mint ignores that for now. Check balance again: spl token balance TOKENADDRESS.
I usually mint big for testing-burn later if needed with spl token burn TOKEN_ADDRESS AMOUNT. Fees? Negligible, ~0.000005 SOL.
Raw tokens are boring. No name, no symbol, no image. Fix with Metaplex magic.
First, prep metadata JSON. Create a file metadata.json:
{ "name": "PizzaSlice", "symbol": "PIZZA", "description": "Slice of the blockchain pie", "image": "https://your image url on arweave or ipfs.com/pizza.png"
} Upload image to Irys (cheap Arweave) or Pinata for IPFS. Free tiers work. Get that URI.
Then initialize: spl token initialize metadata TOKEN_ADDRESS "PizzaSlice" "PIZZA" "https://your metadata uri.json". Sign the tx in terminal or wallet.
Now refresh Phantom-your token shows with logo! Why bother? Exchanges, DEXs like Raydium need this to list.
Decimals locked forever-pick smart. Memecoins? 6-9. Stablecoins? 6 like USDC.
Fixed supply? Revoke mint authority after: spl token authorize TOKEN_ADDRESS mint --disable. Can't mint more. Creates scarcity, good for trust.
Or keep minting forever. Your call. Multisig? Set another wallet as authority for teams.
| Supply Type | Pros | Cons | When I Use It |
|---|---|---|---|
| Fixed | Trustworthy, deflationary hype | No flexibility | Meme coins, NFTs |
| Flexible | Add supply as needed | Rug pull fears | Utility tokens, DAOs |
| Token-2022 | Fees, confidential balances | Newer, less support | Advanced DeFi |
Transfer: spl token transfer TOKENADDRESS 1000 RECIPIENTTOKENACCOUNT.
Don't know their token account? They run spl token create account TOKENADDRESS first, or use ATA formula.
Bulk? Scripts or tools like Squads for airdrops. I scripted one in JS once-looped 500 wallets, cost me 0.01 SOL total.
Issue: Wrong address? Tokens gone forever. Double check.
CLI's fun, but for dApps? Metaplex Umi library. Install: npm init; npm i @metaplex foundation/umi bundle defaults @metaplex foundation/mpl token metadata @metaplex foundation/mpl toolbox.
Full script below. Tweak and run node script.js. Airdrops 1 SOL, uploads image/metadata to Irys (~0.001 SOL), mints 1000 tokens.
import { createUmi } from '@metaplex foundation/umi bundle defaults'
import { createFungible, mplTokenMetadata } from '@metaplex foundation/mpl token metadata'
import { createTokenIfMissing, findAssociatedTokenPda, getSplAssociatedTokenProgramId, mintTokensTo } from '@metaplex foundation/mpl toolbox'
import { generateSigner, percentAmount, createGenericFile, signerIdentity, sol } from '@metaplex foundation/umi'
import { irysUploader } from '@metaplex foundation/umi uploader irys'
import { base58 } from '@metaplex foundation/umi/serializers'
import fs from 'fs' const createAndMintTokens = async () => { const umi = createUmi('https://api.devnet.solana.com').use(mplTokenMetadata()).use(irysUploader()) const signer = generateSigner(umi) umi.use(signerIdentity(signer)) await umi.rpc.airdrop(umi.identity.publicKey, sol(1)) // Upload image const imageFile = fs.readFileSync('./your logo.png') const umiImage = createGenericFile(imageFile, 'logo.png', { tags: [{ name: 'Content Type', value: 'image/png' }] }) const imageUri = (await umi.uploader.upload([umiImage])) // Metadata const metadata = { name: 'YourToken', symbol: 'YT', description: 'Cool token', image: imageUri } const metadataUri = await umi.uploader.uploadJson(metadata) // Mint const mintSigner = generateSigner(umi) const createFungibleIx = createFungible(umi, { mint: mintSigner, name: 'YourToken', uri: metadataUri, sellerFeeBasisPoints: percentAmount(0), decimals: 9 }) const createTokenIx = createTokenIfMissing(umi, { mint: mintSigner.publicKey, owner: umi.identity.publicKey, ataProgram: getSplAssociatedTokenProgramId(umi) }) const mintTokensIx = mintTokensTo(umi, { mint: mintSigner.publicKey, token: findAssociatedTokenPda(umi, { mint: mintSigner.publicKey, owner: umi.identity.publicKey }), amount: BigInt(1000000) }) const tx = await createFungibleIx.add(createTokenIx).add(mintTokensIx).sendAndConfirm(umi) console.log(Tx: https://explorer.solana.com/tx/${base58.deserialize(tx.signature)}?cluster=devnet) console.log(Token: https://explorer.solana.com/address/${mintSigner.publicKey}?cluster=devnet)
} createAndMintTokens()
Errors? 429 on airdrop-switch RPC to Helius free tier. Image fails? Check MIME type.
Honestly, this script's my go to. Deployed 10 tokens last month with it.
Stuck? Here's what bites newbies.
spl token create token --program id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb.Devnet good? Time for real.
solana config set --url https://api.mainnet beta.solana.comSecurity: Backup keys. Use multisig via Squads. Never share seed.
Last thing-burn tokens if testing: spl token burn TOKENADDRESS AMOUNT. Close accounts for SOL refund: spl token close TOKENACCOUNT.