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

Solana web3.js开发:如何通过钱包获取web3.Signer完成SPL代币转账

核心调整逻辑

  • 不需要手动构造web3.Signer实例,钱包适配器已经封装了签名能力,直接调用适配器的signTransaction方法让用户钱包完成签名即可,私钥完全由钱包侧保管,不会暴露给业务代码
  • 原有代码中直接调用transaction.serialize()得到的是未签名交易,发送到链上必然会失败,必须先交给钱包签名
  • 转账NFT的金额应该为1,因为NFT默认小数位为0,不需要乘10^6
  • 无需纠结Token构造函数的payer参数,原有逻辑完全可以不创建Token实例,直接导入SPL相关常量即可完成指令构造

调整后完整代码

import * as web3 from "@solana/web3.js";
import { getPhantomWallet } from "@solana/wallet-adapter-wallets";
import { Token, TOKEN_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID } from "@solana/spl-token";


async sendNFT() {
  const wallet = getPhantomWallet();
  const adapter = wallet.adapter();

  await adapter.connect();
  if (!adapter.connected || !adapter.publicKey) return;
  
  const mintPublicKey = new web3.PublicKey(this.props.nft.data.mint);  
  // 计算发送方的关联代币账户地址
  const fromTokenAccount = await Token.getAssociatedTokenAddress(
    ASSOCIATED_TOKEN_PROGRAM_ID,
    TOKEN_PROGRAM_ID,
    mintPublicKey,
    adapter.publicKey
  );

  // 替换为实际接收地址
  const destPublicKey = new web3.PublicKey("your_destination_address");
  // 计算接收方的关联代币账户地址
  const associatedDestinationTokenAddr = await Token.getAssociatedTokenAddress(
    ASSOCIATED_TOKEN_PROGRAM_ID,
    TOKEN_PROGRAM_ID,
    mintPublicKey,
    destPublicKey
  );

  const receiverAccount = await this.props.connection.getAccountInfo(associatedDestinationTokenAddr);
  const instructions: web3.TransactionInstruction[] = [];  

  // 接收方关联账户不存在时先创建
  if (!receiverAccount) {
    instructions.push(
      Token.createAssociatedTokenAccountInstruction(
        ASSOCIATED_TOKEN_PROGRAM_ID,
        TOKEN_PROGRAM_ID,
        mintPublicKey,
        associatedDestinationTokenAddr,
        destPublicKey,
        adapter.publicKey
      )
    )
  }
  
  // 添加转账指令,NFT转账金额为1
  instructions.push(
    Token.createTransferInstruction(
      TOKEN_PROGRAM_ID,
      fromTokenAccount,
      associatedDestinationTokenAddr,
      adapter.publicKey,
      [],
      1
    )
  );

  // 构造交易
  const transaction = new web3.Transaction().add(...instructions);
  transaction.feePayer = adapter.publicKey;
  transaction.recentBlockhash = (await this.props.connection.getRecentBlockhash()).blockhash;
  
  // 调用钱包适配器签名交易,代替本地用私钥签名的逻辑
  const signedTransaction = await adapter.signTransaction(transaction);
  // 发送签名后的交易
  const transactionSignature = await this.props.connection.sendRawTransaction(
    signedTransaction.serialize(),
    { skipPreflight: true }
  );

  await this.props.connection.confirmTransaction(transactionSignature);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 10:36:05