Read SOL and SPL token balances with @solana/web3.js v2 / @solana/kit: getBalance, findAssociatedTokenPda then getTokenAccountBalance
Situation: you move to @solana/web3.js v2 (renamed @solana/kit in 2025 — same API, new package name) and nothing from v1 tutorials compiles. There is no Connection, no PublicKey, and the docs you find describe 1.95.x. You just want a wallet's SOL balance and its balance of one mint.
Native balance — addresses are branded strings produced by address(), and every RPC method returns a *builder* you must .send():
import { address } from '@solana/kit';
const { value: lamports } = await rpc.getBalance(address(owner)).send();SPL balance — the RPC only knows token *accounts*, so derive the associated token account from (mint, owner) first. The SPL helpers live in a separate package, not in web3.js/kit:
import { findAssociatedTokenPda, TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
const [ata] = await findAssociatedTokenPda({ mint, owner, tokenProgram: TOKEN_PROGRAM_ADDRESS });
const { value: { amount, decimals } } = await rpc.getTokenAccountBalance(ata).send();Footguns worth knowing: forgetting .send() gives you a pending builder object rather than data, with no error; the tokenProgram argument is part of the PDA derivation, so passing TOKEN_PROGRAM_ADDRESS for a Token-2022 mint silently derives a non-existent account and getTokenAccountBalance then fails with "could not find account"; and getTokenAccountBalance throws for an ATA that was never created, so use getTokenAccountsByOwner with a mint filter when existence is uncertain. amount is a raw base-unit string — divide by 10 ** decimals yourself.
Source: adapted from a Stack Exchange answer by steveluscher (question by FunnyFlo), https://solana.stackexchange.com/questions/17807/check-the-balance-of-a-token-for-an-account-address-in-web3-js-version-2-x — CC BY-SA 4.0