使用 Viem.sh 读取NFT合约信息

  • 链创通
  • 更新于 2024-07-13 09:52
  • 阅读 1098

使用Viem.sh读取NFT合约信息

使用 Viem.sh 读取NFT合约信息

一、安装并配置viem

要使用 Viem.sh 读取特定 NFT 合约中的信息,首先,你需要确保在项目中已经安装并配置了 @viem/sh 库。如果还没有安装,可以使用以下命令进行安装:

pnpm install viem

image-20240712213756873.png

二、准备工作

新建viem_nft1文件夹和文件index.js

mkdir viem_nft1
cd viem_nft1 && vim index.js

在此,需要连接到以太坊网络:你需要使用 Viem 库连接到以太坊网络,例如 Infura 或 Alchemy 提供的节点。

其次,定义合约和调用函数:你需要定义 NFT 合约的 ABI 和地址,并调用相应的函数来读取持有人地址和元数据。

你可以替换NFT_TOKEN_ID 为你实际的 NFT 的 Token ID。

编辑文件index.js内容如下:

import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains';
import erc721Abi from './erc721Abi.json' assert { type: 'json' }; 

const client = createPublicClient({
  chain: mainnet,
  transport: http(),
})

const nftContractAddress = '0x0483b0dfc6c78062b9e999a82ffb795925381415'
const tokenId = 'NFT_TOKEN_ID' 

// 读取持有人地址
async function getOwnerOf(tokenId) {
  const owner = await client.readContract({
    address: nftContractAddress,
    abi: erc721Abi,
    functionName: 'ownerOf',
    args: [tokenId],
  })
  return owner
}

// 读取元数据 URI
async function getTokenURI(tokenId) {
  const tokenURI = await client.readContract({
    address: nftContractAddress,
    abi: erc721Abi,
    functionName: 'tokenURI',
    args: [tokenId],
  })
  return tokenURI
}

// 主函数
async function main() {
  try {
    const owner = await getOwnerOf(tokenId)
    console.log(`NFT持有人地址: ${owner}`)

    const tokenURI = await getTokenURI(tokenId)
    console.log(`NFT元数据URI: ${tokenURI}`)

    // 如果需要进一步获取元数据,可以发起HTTP请求获取元数据
    const response = await fetch(tokenURI)
    const metadata = await response.json()
    console.log('NFT元数据:', metadata)
  } catch (error) {
    console.error('读取NFT信息时出错:', error)
  }
}

main()

为了读取 NFT 合约的信息,你需要有该合约的 ABI(应用二进制接口)文件。你可以创建一个 erc721Abi.json 文件,其中包含 ERC-721 标准合约的 ABI。

打开浏览器,依次按照进行点击红框,往下拉寻找NFT合约的ABI

image-20240712215140324.png

点击按钮,复制文件

image-20240712215636474.png

编辑文件 erc721Abi.json 内容复制粘贴如下:

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"Price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TotalNum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"addToBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"numberOfTokens","type":"uint256"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"blacklist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"listClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextOwnerToExplicitlySet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicMintEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"removeFromBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI_","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enable","type":"bool"}],"name":"setPublicMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"mroot","type":"bytes32"},{"internalType":"uint256","name":"step","type":"uint256"}],"name":"setRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enable","type":"bool"},{"internalType":"uint256","name":"step","type":"uint256"}],"name":"setWlMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wlMintStep1Enabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wlMintStep2Enabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"wlmint1","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"wlmint2","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"wlroot1","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wlroot2","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"}]

三、运行项目

首先,在你的项目目录中运行以下命令来初始化一个新的项目:

pnpm init

按照提示填写项目名称、版本等信息。完成后,会生成一个 package.json 文件。

{
  "name": "viem_nft1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

在脚本文件中添加构建模块和依赖

{
  "name": "viem_nft1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",  
  "scripts": {
    "start": "node index.js",
    "build": "echo 'Build step, e.g., webpack or babel'",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {
    "viem": "^2.17.3" 
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

运行以下命令安装依赖构建项目:

pnpm install
pnpm build

填写'NFT_TOKEN_ID' ,比如为1,最后,运行以下命令启动项目:

pnpm start

这里会得出运行结果但是会报一个错误,这个错误是因为 fetch 函数不能直接处理 ipfs:// 协议。为了读取 IPFS 上的内容,你需要通过一个网关来访问 IPFS URL,比如 https://ipfs.io/ipfs/ 或者其他公共 IPFS 网关。

你可以将 IPFS URL 替换为通过公共网关访问的 HTTP URL。下面是更新后的代码:

import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains';
import erc721Abi from './erc721Abi.json' assert { type: 'json' }; 

const client = createPublicClient({
  chain: mainnet,
  transport: http(),
})

const nftContractAddress = '0x0483b0dfc6c78062b9e999a82ffb795925381415'
const tokenId = '1' 

// 读取持有人地址
async function getOwnerOf(tokenId) {
  const owner = await client.readContract({
    address: nftContractAddress,
    abi: erc721Abi,
    functionName: 'ownerOf',
    args: [tokenId],
  })
  return owner
}

// 读取元数据 URI
async function getTokenURI(tokenId) {
  const tokenURI = await client.readContract({
    address: nftContractAddress,
    abi: erc721Abi,
    functionName: 'tokenURI',
    args: [tokenId],
  })
  return tokenURI
}
// 将 IPFS URL 转换为 HTTP URL
function convertIpfsUrl(ipfsUrl) {
  return ipfsUrl.replace('ipfs://', 'https://ipfs.io/ipfs/');
}

// 主函数
async function main() {
  try {
    const owner = await getOwnerOf(tokenId);
    console.log(`NFT持有人地址: ${owner}`);

    const tokenURI = await getTokenURI(tokenId);
    console.log(`NFT元数据URI: ${tokenURI}`);

    // 将 IPFS URL 转换为 HTTP URL
    const httpUrl = convertIpfsUrl(tokenURI);
    console.log(`转换后的HTTP URL: ${httpUrl}`);

    // 发起HTTP请求获取元数据
    const response = await fetch(httpUrl);
    const metadata = await response.json();
    console.log('NFT元数据:', metadata);
  } catch (error) {
    console.error('读取NFT信息时出错:', error);
  }
}

main();
// // 主函数
// async function main() {
//   try {
//     const owner = await getOwnerOf(tokenId)
//     console.log(`NFT持有人地址: ${owner}`)

//     const tokenURI = await getTokenURI(tokenId)
//     console.log(`NFT元数据URI: ${tokenURI}`)

//     // 如果需要进一步获取元数据,可以发起HTTP请求获取元数据
//     const response = await fetch(tokenURI)
//     const metadata = await response.json()
//     console.log('NFT元数据:', metadata)
//   } catch (error) {
//     console.error('读取NFT信息时出错:', error)
//   }
// }

// main()

然后重新运行

pnpm start

结果如下:

@yhbdeMacBook-Air viem_nft1 % pnpm start

> viem_nft1@1.0.0 start /Users/yhb/viem_nft/viem_nft1
> node index.js

(node:93006) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
NFT持有人地址: 0x6897625C2Da7E985e9c22E0d7B27A960Fc81D1D2
NFT元数据URI: ipfs://QmY9wa5FssaBBhLyyC2r649rwfS7CcvH7NG5AJWepeDkGj/1.json
转换后的HTTP URL: https://ipfs.io/ipfs/QmY9wa5FssaBBhLyyC2r649rwfS7CcvH7NG5AJWepeDkGj/1.json
NFT元数据: {
  dna: 'b5940ead98dd50c06ccdb56ccfa37123ff083ca3',
  name: 'ORBIT#1 Metaverse 1 Time and Space',
  description: '',
  image: 'ipfs://QmT3wMgcmm9R1dC1F63rBFdQdGYCfWfpv1D1PXYXTwrEaQ/1.jpg',
  edition: 1,
  date: 1715078282818,
  attributes: [
    { trait_type: 'Category', value: 'Metaverse' },
    { trait_type: 'Color', value: 'Green' },
    { trait_type: 'Planet', value: 'Moderate' },
    { trait_type: 'Years', value: '2018' },
    { trait_type: 'Characters', value: 'Null' },
    { trait_type: 'Shapes', value: 'Square' },
    { trait_type: 'Elements', value: 'Mixed' }
  ]
}
点赞 1
收藏 1
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
链创通
链创通
0x5312...1e69
歪脖山徒步虾