如何使用solana/web3.js v2获取钱包中代币的mint地址
Solana Web3.js 2.0 提取钱包代币Mint地址解决方案
问题描述
能获取钱包内的代币账户数据,但无法从中提取Mint地址,需要拿到所有代币的Mint地址用于API调用,当前使用Solana Web3.js 2.0版本,相关示例较少。
现有代码:
const TOKEN_PROGRAM_ID = address('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA') const { value: tokensInWallet} = await rpc .getTokenAccountsByOwner( address('XXX'), { programId: TOKEN_PROGRAM_ID }, { encoding: 'base64'} ) .send(); console.log(tokensInWallet); //expect mint jtojtomepa8beP8AuQc6eXt5FriJwfFMwQx2v2f9mCL for JTO token tokensInWallet.map(tokenAccount => { const encoded = getBase64Encoder().encode(tokenAccount.account.data[0]); console.log(encoded); //now turn into this format of the mint //base58 encode const mint = getBase58Encoder().encode(tokenAccount.pubkey); console.log(Buffer.from(mint).toString('base64')); })
尝试对数据编码/解码但没有进展,返回的代币账户数据结构如下:
[ { "account": { "data": [ "Cvz4louNq4hIHi0q5onJUsdXrrpkPjkZ6J8uVXlcdsEpwCylBRLH6qBLpURZ/jc3h9wTxgzMrD4rEPcp06WvvwAoa+4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "base64" ], "executable": false, "lamports": 2039280n, "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "rentEpoch": 18446744073709551615n, "space": 165n }, "pubkey": "3UoZPNLp1eynjjCEEcKyv3VcXtoZCe5GdEt2agDezD31" } ]
解决方案
方法1:使用@solana/spl-token库解析(推荐)
Solana的SPL Token库提供了现成的账户布局解析工具,无需手动处理字节:
- 首先安装依赖:
npm install @solana/spl-token
- 修改代码如下:
import { address, Connection } from '@solana/web3.js'; import { AccountLayout } from '@solana/spl-token'; const TOKEN_PROGRAM_ID = address('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'); const rpc = new Connection('https://api.mainnet-beta.solana.com'); // 替换为你的RPC地址 async function getWalletTokenMints(walletAddress: string) { const { value: tokensInWallet } = await rpc .getTokenAccountsByOwner( address(walletAddress), { programId: TOKEN_PROGRAM_ID }, { encoding: 'base64' } ) .send(); const mintAddresses = tokensInWallet.map(tokenAccount => { // 将base64数据转换为Buffer const dataBuffer = Buffer.from(tokenAccount.account.data[0], 'base64'); // 用AccountLayout解析Token账户数据 const accountInfo = AccountLayout.decode(dataBuffer); // 提取并转换为base58格式的Mint地址 const mintAddress = address(accountInfo.mint); return mintAddress; }); console.log('所有代币Mint地址:', mintAddresses); return mintAddresses; } // 调用函数,替换为目标钱包地址 getWalletTokenMints('XXX');
方法2:手动解析字节(无需额外依赖)
如果不想安装额外库,可以手动解析Token Account的二进制数据:Token Account数据中,Mint地址从第32字节开始,连续占32字节(前32字节为账户所有者地址)。
修改代码如下:
import { address, Connection, bs58 } from '@solana/web3.js'; const TOKEN_PROGRAM_ID = address('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'); const rpc = new Connection('https://api.mainnet-beta.solana.com'); async function getWalletTokenMints(walletAddress: string) { const { value: tokensInWallet } = await rpc .getTokenAccountsByOwner( address(walletAddress), { programId: TOKEN_PROGRAM_ID }, { encoding: 'base64' } ) .send(); const mintAddresses = tokensInWallet.map(tokenAccount => { const dataBuffer = Buffer.from(tokenAccount.account.data[0], 'base64'); // 截取32-64字节的Mint地址二进制数据 const mintBuffer = dataBuffer.slice(32, 64); // 转换为base58格式 const mintAddress = bs58.encode(mintBuffer); return mintAddress; }); console.log('所有代币Mint地址:', mintAddresses); return mintAddresses; } getWalletTokenMints('XXX');
说明
- 推荐使用方法1,SPL Token库会处理更多边界情况,后续Token账户结构更新也无需手动调整代码。
- 确保Web3.js版本为2.x,
address函数和rpc调用方式符合2.x规范。
内容的提问来源于stack exchange,提问作者Sebastian_B
相关产品推荐
相关产品推荐

