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

基于Phantom钱包与@solana/web3.js实现Solana主网自定义代币支付方案问询

实现自定义代币支付(Phantom钱包,无需私钥)

Got it, let's break this down—you're totally on the right track avoiding hardcoded keys and unnecessary signer dependencies. Phantom's wallet interface is designed exactly for this scenario where you don't need access to the user's private key, you just need to request their approval for transactions.

Here's a step-by-step solution tailored to your use case:

核心思路

Phantom钱包提供了注入式的API,允许你构建交易并请求用户在钱包弹窗内授权签名,全程无需接触用户私钥。对于SPL自定义代币,我们需要使用TransferChecked指令(而非普通SOL转账指令)来确保金额精度正确。


完整实现流程与代码示例

假设你已经完成了Phantom钱包的基础连接逻辑,下面是关键代码部分:

1. 确认钱包连接与基础配置

import { PublicKey, Transaction, Connection, Token, TOKEN_PROGRAM_ID } from "@solana/web3.js";

// 先检查Phantom是否已注入
if (!window.solana || !window.solana.isPhantom) {
  alert("请先安装并打开Phantom钱包");
  return;
}

// 连接钱包(若未连接)
async function getConnectedWallet() {
  try {
    const { publicKey } = await window.solana.connect();
    return publicKey;
  } catch (err) {
    console.error("用户拒绝连接钱包", err);
    return null;
  }
}

// 配置你的自定义代币与商家账户信息
const CUSTOM_TOKEN_MINT = new PublicKey("替换为你的自定义代币Mint地址");
const TOKEN_DECIMALS = 9; // 你的代币小数位数,比如USDC是6,根据实际设置
const MERCHANT_TOKEN_ACCOUNT = new PublicKey("替换为商家接收代币的账户地址");
const SOLANA_CONNECTION = new Connection("https://api.devnet.solana.com", "confirmed"); // 测试用devnet,上线换mainnet

2. 构建自定义代币转账指令

async function buildTokenTransferTx(userPublicKey) {
  // 获取用户的自定义代币关联账户地址(用户必须已持有过该代币,否则需先创建账户)
  const userTokenAccount = await Token.getAssociatedTokenAddress(
    TOKEN_PROGRAM_ID,
    CUSTOM_TOKEN_MINT,
    userPublicKey
  );

  // 计算转账金额:比如要支付5个代币,转成最小单位(乘以10^小数位数)
  const transferAmount = 5 * Math.pow(10, TOKEN_DECIMALS);

  // 创建TransferChecked指令(确保金额精度)
  return Token.createTransferCheckedInstruction(
    TOKEN_PROGRAM_ID,
    userTokenAccount,
    CUSTOM_TOKEN_MINT,
    MERCHANT_TOKEN_ACCOUNT,
    userPublicKey,
    [],
    transferAmount,
    TOKEN_DECIMALS
  );
}

3. 请求用户签名并发送交易

async function processTokenPayment() {
  const userPublicKey = await getConnectedWallet();
  if (!userPublicKey) return;

  try {
    // 获取最新区块哈希,确保交易有效
    const { blockhash } = await SOLANA_CONNECTION.getLatestBlockhash();
    
    // 构建交易
    const transferInstruction = await buildTokenTransferTx(userPublicKey);
    const transaction = new Transaction({
      recentBlockhash: blockhash,
      feePayer: userPublicKey // 用户支付SOL作为gas费
    }).add(transferInstruction);

    // 请求Phantom签名并发送交易
    const signature = await window.solana.signAndSendTransaction(transaction);
    
    // 等待交易确认
    await SOLANA_CONNECTION.confirmTransaction(signature, "confirmed");
    
    console.log("支付成功!交易签名:", signature);
    // 这里添加支付成功后的业务逻辑(比如发放商品、更新订单状态)
  } catch (err) {
    console.error("支付失败:", err);
    // 处理用户拒绝授权、余额不足、gas费不够等错误场景
  }
}

关键注意事项

  • 用户代币账户:如果用户是第一次持有你的自定义代币,需要先为其创建关联账户,可通过Token.createAssociatedTokenAccountInstruction指令实现,同样通过Phantom请求签名完成。
  • Gas费:用户需要持有少量SOL来支付交易手续费(自定义代币转账本身不消耗代币),可以在前端提示用户确保SOL余额充足。
  • 测试环境:先在Devnet上完成端到端测试,确认代币地址、账户地址和金额计算都正确后再切换到主网。

这样就完全符合你的需求:不需要获取用户私钥,所有签名操作都在Phantom钱包内部完成,安全且合规。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 11:18:12