如何解决Solana中‘Mint需为签名者初始化账户’错误(0x86)
解决Solana Metaplex元数据创建的0x86自定义程序错误
问题描述
使用@solana/web3.js和Metaplex的mpl-token-metadata库开发Solana应用时,创建代币元数据触发SendTransactionError,自定义程序错误码为0x86,错误日志明确提示:Mint needs to be signer to initialize the account。
错误日志
SendTransactionError: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: custom program error: 0x86 at Connection.sendEncodedTransaction at async Connection.sendRawTransaction at async Object.sendTransaction at async TransactionBuilder.sendAndConfirm Logs: - Program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s invoke [1] - Program log: IX: Create - Program 11111111111111111111111111111111 invoke [2] - Program 11111111111111111111111111111111 success - Program log: Mint needs to be signer to initialize the account - Program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s consumed 11404 of 200000 compute units - Program metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s failed: custom program error: 0x86
原代码
import { createV1, updateV1 ,Collection, CreateMetadataAccountV3InstructionAccounts, CreateMetadataAccountV3InstructionDataArgs, Creator, MPL_TOKEN_METADATA_PROGRAM_ID, UpdateMetadataAccountV2InstructionAccounts, UpdateMetadataAccountV2InstructionData, Uses, createMetadataAccountV3, updateMetadataAccountV2, findMetadataPda, CreateV1InstructionAccounts, CreateV1InstructionData, TokenStandard, CollectionDetails, PrintSupply, UpdateV1InstructionData, UpdateV1InstructionAccounts, Data} from "@metaplex-foundation/mpl-token-metadata"; import * as web3 from "@solana/web3.js"; import { PublicKey, createSignerFromKeypair, none, percentAmount, publicKey, signerIdentity, some } from "@metaplex-foundation/umi"; import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'; import { fromWeb3JsKeypair, fromWeb3JsPublicKey} from '@metaplex-foundation/umi-web3js-adapters'; import * as bs58 from "bs58"; const SPL_TOKEN_2022_PROGRAM_ID: PublicKey = publicKey( 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb' ); export function loadWalletKey(keypairFile:string): web3.Keypair { const fs = require("fs"); const loaded = web3.Keypair.fromSecretKey( new Uint8Array(JSON.parse(fs.readFileSync(keypairFile).toString())), ); return loaded; } const INITIALIZE = true; async function main(){ console.log("let's name some token-22 tokens in 2024!"); const myKeypair = loadWalletKey("RRTigmrq7BxQRZchiYNwh8na3dn9uvApUurBi3Fue8a.json"); const mint = new web3.PublicKey("DANK5eskRs1TU5pJK73X9RvG8w8wjM9vHA79qEL4poN8"); const umi = createUmi("https://api.devnet.solana.com"); const signer = createSignerFromKeypair(umi, fromWeb3JsKeypair(myKeypair)) umi.use(signerIdentity(signer, true)) const ourMetadata = { // TODO change those values! name: "xxx", symbol: "xxxx", uri: "xxxx", } if(INITIALIZE){ const onChainData = { ...ourMetadata, // we don't need that sellerFeeBasisPoints: percentAmount(0,2), creators: none<Creator[]>(), collection: none<Collection>(), uses: none<Uses>(), } const accounts: CreateV1InstructionAccounts = { mint: fromWeb3JsPublicKey(mint), splTokenProgram: SPL_TOKEN_2022_PROGRAM_ID } const data: CreateV1InstructionData = { ...onChainData, isMutable: true, discriminator: 0, tokenStandard: TokenStandard.Fungible, collectionDetails: none<CollectionDetails>(), ruleSet: none<PublicKey>(), createV1Discriminator: 0, primarySaleHappened: true, decimals: none<number>(), printSupply: none<PrintSupply>(), } const txid = await createV1(umi, {...accounts, ...data}).sendAndConfirm(umi); console.log(bs58.encode(txid.signature)) } else { const onChainData = { ...ourMetadata, sellerFeeBasisPoints: 0, creators: none<Creator[]>(), collection: none<Collection>(), uses: none<Uses>(), } const accounts: UpdateV1InstructionAccounts = { mint: fromWeb3JsPublicKey(mint), } const data = { discriminator: 0, data: some<Data>(onChainData), updateV1Discriminator: 0, } const txid = await updateV1(umi, {...accounts, ...data}).sendAndConfirm(umi); console.log(bs58.encode(txid.signature)) } } main();
解决方案
错误原因
错误码0x86对应Metaplex的MintMustBeSigner错误,创建元数据时,代币mint账户必须作为交易签名者,以此验证操作的合法性(只有mint的持有者才能初始化其元数据)。原代码仅传入了mint的公钥,未将其作为签名者加入交易。
修复步骤
- 确保持有mint账户的私钥:如果mint是你创建的,你需要保存其keypair文件;若为第三方mint,你无权让它签名,该操作不符合规则。
- 将mint转换为Umi签名者:加载mint的keypair,转换为Umi环境的signer对象,并在
createV1指令的accounts参数中使用该signer,而非单纯的公钥。
修改后的代码示例
import { createV1, updateV1 ,Collection, CreateV1InstructionAccounts, CreateV1InstructionData, Creator, TokenStandard, CollectionDetails, PrintSupply, UpdateV1InstructionAccounts, UpdateV1InstructionData, Data, none, percentAmount, some } from "@metaplex-foundation/mpl-token-metadata"; import * as web3 from "@solana/web3.js"; import { PublicKey, createSignerFromKeypair, publicKey, signerIdentity } from "@metaplex-foundation/umi"; import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'; import { fromWeb3JsKeypair, fromWeb3JsPublicKey} from '@metaplex-foundation/umi-web3js-adapters'; import * as bs58 from "bs58"; const SPL_TOKEN_2022_PROGRAM_ID: PublicKey = publicKey( 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb' ); export function loadWalletKey(keypairFile:string): web3.Keypair { const fs = require("fs"); const loaded = web3.Keypair.fromSecretKey( new Uint8Array(JSON.parse(fs.readFileSync(keypairFile).toString())), ); return loaded; } const INITIALIZE = true; async function main(){ console.log("let's name some token-22 tokens in 2024!"); const myKeypair = loadWalletKey("RRTigmrq7BxQRZchiYNwh8na3dn9uvApUurBi3Fue8a.json"); // 加载mint账户的keypair(替换为你的mint keypair文件路径) const mintKeypair = loadWalletKey("mint-keypair.json"); const mintPublicKey = mintKeypair.publicKey; const umi = createUmi("https://api.devnet.solana.com"); const payerSigner = createSignerFromKeypair(umi, fromWeb3JsKeypair(myKeypair)) // 将mint转换为Umi签名者 const mintSigner = createSignerFromKeypair(umi, fromWeb3JsKeypair(mintKeypair)) umi.use(signerIdentity(payerSigner, true)) const ourMetadata = { name: "xxx", symbol: "xxxx", uri: "xxxx", } if(INITIALIZE){ const onChainData = { ...ourMetadata, sellerFeeBasisPoints: percentAmount(0,2), creators: none<Creator[]>(), collection: none<Collection>(), uses: none<Collection>(), } const accounts: CreateV1InstructionAccounts = { mint: mintSigner, // 使用mint签名者而非公钥 splTokenProgram: SPL_TOKEN_2022_PROGRAM_ID } const data: CreateV1InstructionData = { ...onChainData, isMutable: true, discriminator: 0, tokenStandard: TokenStandard.Fungible, collectionDetails: none<CollectionDetails>(), ruleSet: none<PublicKey>(), createV1Discriminator: 0, primarySaleHappened: true, decimals: none<number>(), printSupply: none<PrintSupply>(), } // 发送交易时,Umi会自动包含mintSigner的签名 const txid = await createV1(umi, {...accounts, ...data}).sendAndConfirm(umi); console.log(bs58.encode(txid.signature)) } else { const onChainData = { ...ourMetadata, sellerFeeBasisPoints: 0, creators: none<Creator[]>(), collection: none<Collection>(), uses: none<Collection>(), } const accounts: UpdateV1InstructionAccounts = { mint: fromWeb3JsPublicKey(mintPublicKey), } const data = { discriminator: 0, data: some<Data>(onChainData), updateV1Discriminator: 0, } const txid = await updateV1(umi, {...accounts, ...data}).sendAndConfirm(umi); console.log(bs58.encode(txid.signature)) } } main();
关键说明
- 签名者传递:在
CreateV1InstructionAccounts中,mint字段必须传入Signer类型,而非单纯的PublicKey,这样Metaplex程序才能验证mint账户的签名。 - 交易签名:Umi的
sendAndConfirm方法会自动收集交易中所有需要的签名者(包括payer和mint),无需手动添加签名。
内容的提问来源于stack exchange,提问作者user23543214
相关产品推荐
相关产品推荐

