【前言】
我們已經知道其實 NFT 是以 ERC-721 協定架設的智能合約,也就是說我們最理想找到 token owner的方法就是利用 we3.js, ethers.js 或者是 opensea.js 和以太坊有關的 JS 套件,或說是有辦法連接到鏈上資料的套件來找到我們想要的東西!
【智能合約(Smart Contract)】
智能合約的意義其實是「在區塊鏈中,自動在合約中正確地判斷如何行動」的一項合約。也就是一段在區塊鏈裡面的程式碼,滿足特定的條件就會觸發,任誰也阻止不了。反之亦然,誰也沒辦法在這個智能合約的地址上,不經由其他區塊同意,隨便新增一個不合規章的節點。所謂的以太坊開發者協議 ERC(Ethereum Request for Comments)就是智能合約。
那在智能合約之中應該要提供一個 API,像是 ERC-721 裡面的 function ownerOf(uint256 _tokenId) 或相關的 INTERFACE。這樣一個方便普通人使用的查詢工具,才能夠讓大家都確認正確無誤的所有權。
【But...How to get the token's owner?】
所以我們要怎麼在網站上自動(前端、後端)取得 Token's 的 Ownership 呢?
我目前想到的方法有幾個:
ownerOf
得到 Ownership,然後把資料儲存在後端資料庫中,並且在需要時從前端調用資料查詢。好後面兩個方法是個怪方法,但至少是做得出來的,只是我覺得效率非常不好,在網站上的呈現也會非常差,所以我們聚焦在上面三個方法!
【we3.js ? ethers.js : opensea.js】
如果我們透過 web3.js 來找尋 Token Owners 呢,在論壇上有的人可以有的人不行,那我們到底可不可以用 we3.js 抓到 ERC721 合約的 token 資料呢?
有人說抓的到資料:
retrieving web3 contract.ownerOf NFT ERC721
有人說抓不到資料:
How to find all ERC721 compliant NFTs owned by an address? (Web3 JS)
後來又查了一些 web3.js with erc721 的資料:
List ERC721 tokens owned by a user on a web page
Get ERC721 token total supply using web3.js
而 ethers.js 貌似翻過了整個官方文件都沒找到可以套用在 ERC-721 的工具,只有在這個討論串裡面有提到。如果是利用 ABI 的話好像也只能用在 ERC-20,嗎。
經過整理還有一些研究之後,直接來試試看就知道可不可以了!
【Trying we3.js to get ERC-721 Token Owner】
我使用了以下程式碼跑不動,回報的錯誤是 eth 不屬於 web3 以內QQ。我想可能是我引入套件有問題只是我不知道怎麼解決。
import * as web3 from 'web3'
import { useEffect, useState } from "react";
let ABI = [
// balanceOf
{
"constant":true,
"inputs":[{"name":"tokenId","type":"uint256"}],
"name":"ownerOf",
"outputs":[{"name":"owner","type":"address"}],
"type":"function"
},
// decimals
{
"constant":true,
"inputs":[],
"name":"decimals",
"outputs":[{"name":"","type":"uint8"}],
"type":"function"
}
];
export function OwnerOf(account, id) {
const [a, setA] = useState({
tokenAddress: "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
// https://opensea.io/assets/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d/6445
tokenId: id, // Token ID
schemaName: 'ERC721'
});
const [accountAddress, setAccountAddress] = useState(account)
// https://opensea.io/MachiBigBrother
const [OwnerShip, setOwnerShip] = useState(false)
useEffect(() => {
// STEP 1:在 useEffect 中定義 async function 取名為 fetchData
const fetchData = async () => {
// STEP 2:使用 await 等待 API 取得回應後才繼續
const cc = new web3.eth.Contract(ABI, a.tokenAddress);
const oo = await cc.methods.ownerOf(a.tokenId).call();
console.log("hiii: " + oo);
...
fetchData();
}, []);
return (
...
);
}
【小結】
我確實早就知道 opensea.js 可以做到想要做的事情,只是想試試看其他方法呵呵。結論是我即便看了 stackoverflow 還是被屌虐啦!希望明天 opensea.js 可以幫我討回公道嗚嗚。