如何基于ethers.js与Infura通过后端代码实现ERC-721 NFT转至钱包
结论
完全可以仅通过后端代码完成Decentraland生态ERC-721标准NFT的指定地址转账,你当前选用的Infura节点服务+ethers.js技术栈完全适配该场景,不需要依赖前端交互、用户签名组件。
前置准备
- 对应网络的Infura访问权限:Decentraland核心资产部署在以太坊主网,若操作测试网资产则开通对应Sepolia等测试网的Infura API访问权限,拿到API Key
- 转出权限凭证:后端持有转出方钱包的私钥(若使用授权操作模式,持有被授权地址的私钥也可),私钥严禁硬编码在代码中,必须通过环境变量或专用密钥管理服务存储
- 核心转账参数:提前确认目标NFT对应的合约地址、要转账的NFT对应的tokenId、接收方钱包地址,三个参数任意一个填错都会导致资产永久丢失,链上交易无撤销机制
- 预留Gas费:转出钱包需持有对应网络的原生ETH作为Gas费,ERC-721转账单交易Gas消耗通常在4万~10万区间,按实时网络Gas价格预存足够余额即可
代码实现(基于ethers.js v6)
优先使用ERC-721标准的safeTransferFrom方法完成转账,该方法会自动校验接收地址是否支持ERC-721资产接收,避免NFT转入不支持NFT的合约地址永久锁死。
- 先安装依赖
npm install ethers@6 dotenv
- 可直接运行的参考代码
require('dotenv').config() const { ethers, JsonRpcProvider, Wallet, Contract } = require("ethers"); // 初始化Infura节点连接 const provider = new JsonRpcProvider(`https://mainnet.infura.io/v3/${process.env.INFURA_API_KEY}`); // 初始化签名钱包 const signer = new Wallet(process.env.SENDER_PRIVATE_KEY, provider); // ERC-721最小可用ABI,仅保留转账、权属查询方法即可,不需要引入全量合约ABI const MIN_ERC721_ABI = [ "function safeTransferFrom(address from, address to, uint256 tokenId) external payable", "function ownerOf(uint256 tokenId) external view returns (address)", "function getApproved(uint256 tokenId) external view returns (address)" ]; // 初始化目标NFT合约实例,替换为你要操作的Decentraland NFT合约地址 const NFT_CONTRACT_ADDR = "替换为目标NFT的合约地址"; const nftContract = new Contract(NFT_CONTRACT_ADDR, MIN_ERC721_ABI, signer); async function transferNft() { // 替换为实际业务参数 const RECEIVE_ADDR = "替换为接收方钱包地址"; const TARGET_TOKEN_ID = BigInt("替换为要转账的NFT的tokenId"); // 大数值用BigInt处理避免精度丢失 try { const senderAddr = await signer.getAddress(); // 前置校验,避免链上报错浪费Gas const nftOwner = await nftContract.ownerOf(TARGET_TOKEN_ID); const approvedAddr = await nftContract.getApproved(TARGET_TOKEN_ID); if (nftOwner.toLowerCase() !== senderAddr.toLowerCase() && approvedAddr.toLowerCase() !== senderAddr.toLowerCase()) { throw new Error("当前签名地址无该NFT的转账权限"); } // 发起交易,可根据需要自定义Gas参数 const tx = await nftContract.safeTransferFrom( nftOwner, RECEIVE_ADDR, TARGET_TOKEN_ID, { gasLimit: 100000 // 手动设置Gas上限,避免节点自动估算偏差 } ); console.log("交易已发起,交易哈希:", tx.hash); // 等待交易上链确认 const txReceipt = await tx.wait(); console.log("转账完成,交易打包区块高度:", txReceipt.blockNumber); } catch (e) { console.error("转账失败:", e.message); } } transferNft()
- 环境变量配置参考,在项目根目录新建
.env文件,加入以下内容,同时把.env加入.gitignore避免提交到代码仓库:
INFURA_API_KEY=你的Infura API Key SENDER_PRIVATE_KEY=转出方钱包私钥(去掉0x前缀也可,ethers会自动识别)
实操避坑建议
- 主网操作前必须先在测试网跑通全流程:用Sepolia测试网领测试ETH、mint测试ERC-721资产,完整走通部署、转账、确认流程,确认参数逻辑无问题再切主网
- 挂单中的NFT无法直接转账:如果目标NFT在Decentraland市场或其他NFT平台挂了售卖单,资产会被授权给平台合约,需要先取消挂单、收回授权才能发起转账
- 严禁给没有开源、未验证支持ERC-721接收的合约地址转NFT,即使用
safeTransferFrom也要提前确认,避免资产锁死 - Infura报错优先排查两个点:一是API Key是否泄露被他人盗用超出请求额度,二是网络选择是否和资产所在网络匹配
- 所有核心参数(合约地址、接收地址、tokenId)在发起交易前做二次校验,最好加人工确认环节,链上交易不可回滚,转错无法找回
内容的提问来源于stack exchange,提问作者Raidel Ross
相关产品推荐
相关产品推荐

