如何使用solana/web3.js获取钱包中的全部代币与NFT
用solana/web3.js获取Solana钱包的代币与NFT列表
准备工作
先安装必要的依赖包:
npm install @solana/web3.js @solana/spl-token @metaplex-foundation/js
获取代币列表(含余额)
核心思路是先拉取目标账户下的所有SPL Token账户,再逐个解析代币的元数据与余额:
import { Connection, PublicKey, Keypair } from '@solana/web3.js'; import { getTokenAccountsByOwner, getMint, getAccount } from '@solana/spl-token'; import { Metaplex, keypairIdentity } from '@metaplex-foundation/js'; // 目标钱包地址 const targetAddr = new PublicKey('HEGfxcbHPdkpxZJyqPaGevaAkCGfuaB1mHF1cUv2bTGe'); // 连接Solana主网RPC(可替换为devnet或自定义节点) const connection = new Connection('https://api.mainnet-beta.solana.com'); // 初始化Metaplex用于读取元数据 const metaplex = Metaplex.make(connection) .use(keypairIdentity(Keypair.generate())); // 临时密钥对,仅用于读操作 async function fetchWalletTokens() { // 获取账户下所有Token账户 const tokenAccounts = await getTokenAccountsByOwner(connection, targetAddr, { programId: new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA') }); const tokenList = []; for (const { pubkey } of tokenAccounts.value) { const accountData = await getAccount(connection, pubkey); const mintAddr = accountData.mint; const rawBalance = accountData.amount; // 获取代币小数位信息 const mintInfo = await getMint(connection, mintAddr); const decimals = mintInfo.decimals; const formattedBalance = rawBalance / (10 ** decimals); // 获取代币元数据(名称、符号) try { const metadata = await metaplex.nfts().findByMint({ mintAddress: mintAddr }); tokenList.push({ mint: mintAddr.toBase58(), name: metadata.name, symbol: metadata.symbol, balance: formattedBalance.toFixed(2) }); } catch (err) { // 兼容无标准元数据的代币 tokenList.push({ mint: mintAddr.toBase58(), name: '未知代币', symbol: 'UNKNOWN', balance: formattedBalance.toFixed(2) }); } } return tokenList; } // 执行并打印结果 fetchWalletTokens().then(tokens => { console.log('---账户(HEGfxcbHPdkpxZJyqPaGevaAkCGfuaB1mHF1cUv2bTGe)---'); console.log('代币:'); tokens.forEach(token => { console.log(`${token.mint} ${token.symbol} ${token.balance}`); }); });
获取NFT列表
NFT属于SPL Token的特殊类型:小数位为0、余额为1,以此为筛选条件即可提取NFT:
async function fetchWalletNFTs() { const tokenAccounts = await getTokenAccountsByOwner(connection, targetAddr, { programId: new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA') }); const nftList = []; for (const { pubkey } of tokenAccounts.value) { const accountData = await getAccount(connection, pubkey); const mintAddr = accountData.mint; // 筛选NFT特征:小数位0 + 余额为1 const mintInfo = await getMint(connection, mintAddr); if (mintInfo.decimals !== 0 || accountData.amount.toNumber() !== 1) { continue; } // 获取NFT元数据 try { const nft = await metaplex.nfts().findByMint({ mintAddress: mintAddr }); nftList.push({ mint: mintAddr.toBase58(), name: nft.name, image: nft.json?.image || '无图片', collection: nft.collection?.name || '无系列' }); } catch (err) { continue; } } return nftList; } // 执行并打印结果 fetchWalletNFTs().then(nfts => { console.log('NFTs:'); nfts.forEach(nft => { console.log(`${nft.mint} ${nft.name} ${nft.image}`); }); });
注意事项
- RPC节点:主网公共节点有请求速率限制,建议使用付费节点(如QuickNode)提升稳定性
- 异常处理:部分代币/NFT可能未遵循标准元数据规范,需做好容错
- 性能优化:可通过批量请求减少RPC调用次数,提升获取速度
内容的提问来源于stack exchange,提问作者R2R
相关产品推荐
相关产品推荐

