Solana代币元数据创建失败问题求助及代码排查
Solana元数据创建失败:切片索引越界问题解决
问题诊断
错误日志Panicked at 'range end index 36 out of range for slice of length 0'的核心原因是类型不匹配:
- 你在
main.js中传递给metadata函数的是Mint地址的Base58字符串,但Umi框架的createMetadataAccountV3方法需要的是Umi兼容的PublicKey实例,而非原始字符串。 - 直接传递字符串会导致元数据程序无法正确定位到Mint账户,读取到的账户数据长度为0,当程序尝试访问第36字节的Mint头部信息时触发越界panic。
- 额外问题:
main.js调用metadata(mint, mintAddress)时传递了两个完全相同的字符串参数,属于冗余传参,容易造成混淆。
解决方案
- 统一类型转换:在
new.js的metadata函数中,将传入的Base58字符串转换为Umi认可的PublicKey实例。 - 清理冗余传参:简化
main.js的调用逻辑,只传递必要的Mint地址字符串。 - 确保参数完整性:明确指定
createMetadataAccountV3所需的payer账户(Umi可自动推导,但显式声明更稳妥)。
修改后的代码示例
1. main.js 调用逻辑修改
// 原代码 createMintAccountAndMintTokens() .then((mintAddress) => { mint = mintAddress; return metadata(mint, mintAddress); // 冗余传参 }) // 修改后 createMintAccountAndMintTokens() .then((mintAddress) => { return metadata(mintAddress); // 只传必要的Mint地址字符串 })
2. new.js 核心逻辑修改
// 首先导入Umi的publicKey方法 const { Collection, CreateMetadataAccountV3InstructionAccounts, CreateMetadataAccountV3InstructionDataArgs, Creator, MPL_TOKEN_METADATA_PROGRAM_ID, UpdateMetadataAccountV2InstructionAccounts, UpdateMetadataAccountV2InstructionData, Uses, createMetadataAccountV3, updateMetadataAccountV2, findMetadataPda, } = require("@metaplex-foundation/mpl-token-metadata"); const web3 = require("@solana/web3.js"); const { PublicKey, createSignerFromKeypair, none, signerIdentity, some, publicKey, // 新增导入 } = require("@metaplex-foundation/umi"); const { createUmi } = require("@metaplex-foundation/umi-bundle-defaults"); const { fromWeb3JsKeypair, fromWeb3JsPublicKey, } = require("@metaplex-foundation/umi-web3js-adapters"); function loadWalletKey(privateKeyBytes) { return web3.Keypair.fromSecretKey(new Uint8Array(privateKeyBytes)); } const INITIALIZE = true; // 修改metadata函数的参数和内部逻辑 async function metadata(mintAddress) { try { console.log("Let's name some tokens in 2024!"); console.log("Mint Address", mintAddress); const metadataDetails = { name: "GUDS Coin", symbol: "GUDS", uri: "https://raw.githubusercontent.com/CHToken/LoomDeployerBot/main/metadata.json", }; const privateKeyBytes = process.env.PRIVATE_KEY.split(",").map(Number); const umi = createUmi("https://api.devnet.solana.com"); const signer = createSignerFromKeypair( umi, fromWeb3JsKeypair(loadWalletKey(privateKeyBytes)) ); umi.use(signerIdentity(signer, true)); // 关键:将字符串转换为Umi的PublicKey实例 const mint = publicKey(mintAddress); const onChainData = { ...metadataDetails, sellerFeeBasisPoints: 0, creators: none(), collection: none(), uses: none(), }; if (INITIALIZE) { const accounts = { mint: mint, // 使用转换后的PublicKey mintAuthority: signer, payer: signer, // 显式指定payer,Umi也可自动填充,但显式更清晰 }; const data = { isMutable: true, collectionDetails: null, data: onChainData, }; const txid = await createMetadataAccountV3(umi, { ...accounts, ...data, }).sendAndConfirm(umi); console.log("Metadata Creation Signature:", txid); } else { const data = { data: some(onChainData), discriminator: 0, isMutable: some(true), newUpdateAuthority: none(), primarySaleHappened: none(), }; const accounts = { metadata: findMetadataPda(umi, { mint: mint }), // 同样使用转换后的PublicKey updateAuthority: signer, }; const txid = await updateMetadataAccountV2(umi, { ...accounts, ...data, }).sendAndConfirm(umi); console.log(txid); } } catch (error) { console.error("Error during metadata creation:", error); throw error; } } // Export the metadata function to be used in main.js module.exports = { metadata };
验证步骤
- 重新运行代码,检查交易是否成功上链。
- 通过Solana浏览器查看Mint账户的元数据是否已正确关联。
内容的提问来源于stack exchange,提问作者Techy Tro
相关产品推荐
相关产品推荐

