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
相关产品推荐
相关产品推荐

