You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决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的公钥,未将其作为签名者加入交易。

修复步骤

  1. 确保持有mint账户的私钥:如果mint是你创建的,你需要保存其keypair文件;若为第三方mint,你无权让它签名,该操作不符合规则。
  2. 将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:44:54