前端
继上一篇《React Native DApp 开发全栈实战·从 0 到 1 系列(NFT交易-合约部分)》,本文进入"前端交互"环节:用 ethers.js 一行行打通 铸造 → 授权 → 挂单 → 购买 的完整闭环。示例拆成三步:
- 预览 :
balanceOf
拉取用户 NFT,tokenURI
解析 IPFS 元数据,直接渲染。- 上架 :
create
铸造新 NFT;approve
一键授权给市场合约;list
挂单待售。- 购买 :买家调用
buy
,付款即成交,链上所有权瞬间转移。
前置准备
- hardhat启动网络节点 :npx hardhat node
- 合约编译 :npx hardhat compile 生成对应的xxx.json用获取abi等相关信息
- 合约部署 :npx hardhat deploy --tags MyNFT,OZMarketplace 获取合约地址(NFT和交易NFT的合约地址)
- 节点的私钥导入钱包 :用来与合约交互时支付对应的gas费
核心代码
代码说明:
- 拿到当前账号的balanceOf
- 循环tokenid数组拿到ipfs文件
- 解析ipfs文件
- 前端展示
1.预览铸造的NFT
javascript
import { abi } from "@/abi/SimpleClosedNFT.json";
import * as ethers from "ethers";
const [NFTList,setNFTList]=useState([])
const nftListFn= async ()=>{
const provider = new ethers.providers.Web3Provider(window.ethereum);
await provider.send('eth_requestAccounts', []); // 唤起钱包
const signer = await provider.getSigner();
const nft = new ethers.Contract("0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",abi, signer);//合约地址、abi、
const userAddress=await signer.getAddress()
console.log("当前用户",userAddress)
const nftLength= await nft.balanceOf(userAddress)
const nftList=[]
for(let i=0;i<nftLength.toString();i++){
nftList.push(await nft.tokenURI(i+1))
}
let nftArr=[]
nftList.map((item,index)=>{
fetch(item).then(r => r.json()).then(data=>{
nftArr.push({...data,id:index+1})
setNFTList([...nftArr])
})//解析ipfs上传的json文件
})
}
useEffect(()=>{
nftListFn()
},[])
2.NFT铸造、授权、挂单
代码说明:
- 1.先铸造一个nft
- 2.在把铸造nft授权给nft交易合约
- 3.把授权的nft挂单
javascript
import { abi as MarketplaceABI } from "@/abi/OZMarketplace.json";
import { abi as NFTABI } from "@/abi/SimpleClosedNFT.json";
import * as ethers from 'ethers';
const mintNFT=async ()=>{
const provider = new ethers.providers.Web3Provider(window.ethereum);
console.log("创建NFT")
await provider.send('eth_requestAccounts', []); // 唤起钱包
const signer = await provider.getSigner();
const nftAddress="0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9"
const nft = new ethers.Contract("0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9",NFTABI, signer);//nft合约
const sellContract = new ethers.Contract("0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8", MarketplaceABI, signer);//nft交易合约
const uri = "https://zygomorphic-magenta-bobolink.myfilebase.com/ipfs/QmQT8VpmWQVhUhoDCEK1mdHXaFaJ3KawkRxHm96GUhrXLB"//ipfs文件
const price = ethers.utils.parseEther(priceV.toString());//数字价格
console.log(price)
try{
const tx= await nft.create(uri,price,royalty,{value:price})
const receipt = await tx.wait()
const tokenId = receipt.logs.map(l => nft.interface.parseLog(l)).find(e => e.name === "Transfer")?.args[2];//铸造成功后获取nft的id
console.log("tokenId =", tokenId.toString());
console.log(await nft.tokenURI(tokenId.toString()))//查看ipfs相关信息
console.log("nft的所有者",await nft.ownerOf(tokenId.toString()))
const mintPrice=await nft.mintPrice(tokenId.toString())
console.log("nft的价格",ethers.utils.formatEther(mintPrice))
//授权
const txApprove=await nft.approve("0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8", tokenId.toString());//把铸造的nft授权交易合约
const receiptApprove = await txApprove.wait();
console.log("授权成功","gas消耗:",receiptApprove.gasUsed , "gas价格:",receiptApprove.gasPrice)
console.log("查看授权地址",await nft.getApproved(tokenId.toString()))
//挂单
const listTx=await sellContract.list(tokenId.toString(),ethers.utils.parseEther("1"))
console.log("挂单成功",await listTx.wait())
router.push({
pathname:"/home/nftDetails",
params:{
tokenId:tokenId.toString(),
}
})
}catch(err){
console.log(err)
}
}
3.购买NFT
代码说明:
- 1.获取交易tokenid
- 2.对当前的nft进行售卖
javascript
import { abi as MarketplaceABI } from "@/abi/OZMarketplace.json";
import { abi as NFTABI } from "@/abi/SimpleClosedNFT.json";
import { useLocalSearchParams, useRouter } from 'expo-router';
import * as ethers from 'ethers';
const { tokenId } = useLocalSearchParams();//获取交易的tokenid
const sellFn= async ()=>{
const provider = new ethers.providers.Web3Provider(window.ethereum);
await provider.send('eth_requestAccounts', []); // 唤起钱包
const signer = await provider.getSigner();
const user = await signer.getAddress();
console.log("当前账户", user);
const nftContract = new ethers.Contract("0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9", NFTABI, signer);//nft合约
const sellContract = new ethers.Contract("0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8", MarketplaceABI, signer);//nft交易合约
const owner = await nftContract.ownerOf(1);
console.log("所有者",owner)
const price = ethers.utils.parseEther("1");
//售卖
const selltx=await sellContract.buy(tokenId,{value:price})
const selltxsuccess = await selltx.wait();
console.log("购买成功","gas消耗:",selltxsuccess.gasUsed , "gas价格:",selltxsuccess.gasPrice)
console.log("nft的所有者",await nftContract.ownerOf(tokenId))
}
效果图
总结
快速预览表
步骤 | 核心操作 | 关键 API |
---|---|---|
1. 预览 | 查询用户 NFT 列表 | balanceOf + tokenURI |
2. 铸造 | 创建 NFT | nft.create(uri, price, royalty, {value}) |
3. 授权 | 授权给市场合约 | nft.approve(marketplace, tokenId) |
4. 挂单 | 把 NFT 挂到市场 | marketplace.list(tokenId, price) |
5. 购买 | 买家支付购买 | marketplace.buy(tokenId, {value}) |
以上就是前端与合约交互的全部过程,整个流程遵循 "铸造 → 授权 → 挂单 → 购买" 的标准 NFT 交易闭环,代码可直接运行于 Hardhat 本地节点,便于本地调试与二次开发。