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

如何无需自建铸造账户,通过Phantom钱包在Solana链上铸造NFT

解决方案

完全可以直接使用Phantom钱包完成铸造,不需要先通过随机生成的密钥对中转,核心逻辑是把原来由本地生成Keypair完成的签名操作,替换为调用Phantom钱包的签名能力即可,Phantom不会向网页暴露私钥,所有签名操作都在钱包内部完成,安全性有保障。

核心修改点

  • 补充Phantom钱包连接逻辑,获取用户授权的钱包公钥作为付款方、铸币权限方
  • 移除本地随机生成Keypair的相关逻辑,不再需要中转账户
  • 所有交易构造完成后调用Phantom的signAndSendTransaction方法完成签名上链,不需要传入本地私钥
  • 直接将代币铸造到Phantom钱包的关联代币账户,省略额外转账步骤,降低gas消耗

适配后的完整代码

import * as web3 from '@solana/web3.js';
import * as splToken from '@solana/spl-token';
 
const getProvider = async () => {
  if ("solana" in window) {
    const provider = window.solana;
    if (provider.isPhantom) {
      // 新增连接逻辑,请求用户授权连接钱包
      await provider.connect();
      console.log("Phantom已连接");
      return provider;
    }
  } else {
    alert("请先安装Phantom钱包");
  }
};

const mintingTest = async () => {
  const phantomProvider = await getProvider();
  // 直接使用Phantom钱包的公钥作为所有操作的权限方
  const walletPublicKey = phantomProvider.publicKey;
  console.log("钱包公钥: ", walletPublicKey.toString());

  const connection = new web3.Connection(
    web3.clusterApiUrl('devnet'),
    'confirmed',
  );

  // 1. 新建mint账户
  const mint = web3.Keypair.generate();
  // 计算mint账户所需租金
  const lamports = await splToken.getMinimumBalanceForRentExemptMint(connection);

  // 构造创建mint账户的交易
  const transaction = new web3.Transaction().add(
    // 创建账户指令
    web3.SystemProgram.createAccount({
      fromPubkey: walletPublicKey,
      newAccountPubkey: mint.publicKey,
      space: splToken.MINT_SIZE,
      lamports,
      programId: splToken.TOKEN_PROGRAM_ID,
    }),
    // 初始化mint指令
    splToken.createInitializeMintInstruction(
      mint.publicKey,
      0, // 铸NFT的话小数位设为0,FT可自定义
      walletPublicKey, // 铸币权限
      null, // 冻结权限,不需要可以设为null
      splToken.TOKEN_PROGRAM_ID
    )
  );

  // 让Phantom签名并发送交易
  transaction.feePayer = walletPublicKey;
  transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
  // 这里要签名mint账户的私钥,因为是新建的账户,本地生成的所以可以直接加
  transaction.partialSign(mint);
  // 剩余部分让Phantom签名
  const signedTx = await phantomProvider.signTransaction(transaction);
  const txId = await connection.sendRawTransaction(signedTx.serialize());
  await connection.confirmTransaction(txId, 'confirmed');
  console.log("Mint账户创建成功,地址:", mint.publicKey.toString());

  // 2. 获取/创建钱包的关联代币账户
  const tokenAccount = await splToken.getOrCreateAssociatedTokenAccount(
    connection,
    // 这里传phantomProvider作为signer,会自动调用钱包签名创建账户(如果不存在的话)
    phantomProvider,
    mint.publicKey,
    walletPublicKey
  );
  console.log("关联代币账户地址:", tokenAccount.address.toString());

  // 3. 铸造代币到自己的关联账户
  const mintTx = new web3.Transaction().add(
    splToken.createMintToInstruction(
      mint.publicKey,
      tokenAccount.address,
      walletPublicKey,
      1, // 铸1个,因为小数位是0,就是1个NFT
      [],
      splToken.TOKEN_PROGRAM_ID
    )
  );
  mintTx.feePayer = walletPublicKey;
  mintTx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
  const signedMintTx = await phantomProvider.signTransaction(mintTx);
  const mintTxId = await connection.sendRawTransaction(signedMintTx.serialize());
  await connection.confirmTransaction(mintTxId, 'confirmed');
  console.log("铸造成功,交易ID:", mintTxId);

  // 查询余额
  const balance = await splToken.getMint(connection, mint.publicKey);
  console.log("当前铸造总量:", balance.supply.toString());
};

注意事项

  • 测试前请确保你的Phantom钱包切换到了Devnet网络,且有足够的Devnet SOL支付交易手续费
  • 代码中默认是铸造NFT的配置,如果要铸造可拆分的同质化代币,可自行调整小数位和铸造数量
  • 所有需要签名的操作都会触发Phantom钱包的确认弹窗,手动确认后才会执行上链操作

内容的提问来源于stack exchange,提问作者Tabish Shafi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 10:30:00