iT邦幫忙

2021 iThome 鐵人賽

DAY 23
1
Modern Web

All In One NFT Website Development系列 第 23

Day 23【Tokens' Owner】FUN SIDE PROJECT

  • 分享至 

  • xImage
  •  

fun_projects.jpg

【前言】
終於到了驗證的最後一步啦,感覺時間過得很快,一眨眼就到了這裡,網站也變得非常完整。感謝大家的陪伴,讓我們繼續邁向終點吧!

【定義 Ownership】
接續著上次的內容,這邊我們可以藉由 bignumber.js 的函數 toString() 來轉成字串,並藉此定義 OwnerShip

console.log(balance.toNumber());

if(balance.toString() === "1"){
  setOwnerShip(true);
}

  console.log(OwnerShip);
};

然後我們就可以傳出 OwnerOf() 這個函數,屆時就可以利用 OwnerOf().OwnerShip 來得到到底這個 Token 是不是屬於當前登入者的!

export function OwnerOf(account, id) {
	const [a, setA] = useState({
    tokenAddress: "我們智能合約的地址", 
    tokenId: id, // Token ID
    schemaName: 'ERC721'
  });
  const [accountAddress, setAccountAddress] = useState(account)
  const [OwnerShip, setOwnerShip] = useState(false)

  useEffect(() => {
    const fetchData = async () => {
      const balance = await seaport.getAssetBalance({
        accountAddress: accountAddress,
        asset: {
          tokenAddress: a.tokenAddress,
          tokenId: a.tokenId,
          schemaName: a.schemaName
         },
      })
      console.log(balance.toString());

      if(balance.toString() === "1"){
        setOwnerShip(true);
      }
    };
    fetchData();
  }, []);

  return (
    { OwnerShip }
  );
}

【資料傳遞】
大家還記得我們那時候取得使用者登入帳號的部分嗎!現在我們要把資料傳出來。

首先先在登入區取得當前登入者的帳戶資料,也可以透過導入 web3.js 套件之後利用 web3.eth.coinbase 的方式取得!之後我們就不需要登入者再輸入一次以太坊地址了,我們使用自動填入的功能。

此外我們在導至 VIP 頁面的時候也要順便把使用者帳戶利用 react-router-domLink 可以附帶 state 的功能傳出去,當然也可以到 VIP 頁面的時候用上述方法重新抓一次地址及使用者欲登入的 id,或從後端直接調資料,不過我就想試試看這個方法。

export function LoginForm(props) {
  const [ accounts, setAccounts ] = useState([]);
  const [ inputID, setInputID ] = useState('');
	...
  useEffect(() => {
    window.ethereum
    .request({ method: 'eth_requestAccounts' })
    .then((newAccounts) => setAccounts(newAccounts));
    ...
    
  }, []);

  return (
    <BoxContainer>
      ...
      <SubmitButton type="submit" to={{
                          pathname: "/VIP",
                          state: { ac: accounts,
                                   id: inputID}
                        }}>Enter</SubmitButton>
      ...
    </BoxContainer>
  );
}

這邊有個小細節是因為我們只會發行一萬隻的角色,如果這時候使用者隨便填入一個智能合約中不存在的 id 會導致 compiler error,所以特別在 button tagstyle 利用 pointerEvents 的限制就可以解決問題!

export function LoginForm(props) {
  const [ accounts, setAccounts ] = useState([]);
  const [ inputID, setInputID ] = useState('My Dino ID');
  const [ go, setGo ] = useState({ pointerEvents: "none" })
  ...
  useEffect(() => {
    var i = Number(inputID);
    if( 0 <= i && i <= 9999){
      setGo({pointerEvents: "auto" })
    }
    else{
      setGo({pointerEvents: "none" })
    }
  }, [inputID]);

  return (
    <BoxContainer>
      <Input type="text" placeholder="My Dino ID" value={inputID} onInput={e => setInputID(e.target.value)} />
      <Input type="text" placeholder="My Ethereum Address" value={ accounts } onInput={e => setAccounts(e.target.value)} />
      ...
			<SubmitButton  type="submit" style={ go } to={{
													                          pathname: "/VIP",
													                          state: { ac: accounts,
													                                   id: inputID}
													                        }}>Enter</SubmitButton>
			...
    </BoxContainer>
  );
}

pointer-events - CSS(层叠样式表) | MDN

在這邊我們先 call UseLocation 出來,然後利用 state.ac 就可以得到我們從前一個地方來的 state

import { useLocation } from "react-router-dom";
...

export function VIP(props) {
  ...
  const location = useLocation();
  const [accounts, setAccounts] = useState(location.state.ac);
  const id = location.state.id;
  const OS = OwnerOf(accounts[0], id).OwnerShip;
  ...
  return (
    <Wrapper>
      ...
    </Wrapper>
  );
}

這邊可以確實接收到資料,其中依序 print 出的是: 0 表示 accounts 以及 Token 有 0 組契合;登入者的地址;欲查詢 Ownership 的 Token IDOwnership

圖片 25.png

【驗證成功 & 驗證失敗】
我發現 call opnesea.js 的 getAssetBalance() 會有一些延遲才會得到真正的 ownership,所以我們必須要有一個 Loading Message。這邊就不多加敘述了,因為前面做過很多次方法都差不多!

如果今天是驗證失敗的話我們就要導回到 DINO Login 的地方,但因為 DINO Login 的使用者地址是直接抓 window.ethereum 取得的,所以就不用像上面一樣使用 react-router-domLink 搭配UseLocation 的方式找到地址。

export function VIP(props) {
  ...
  return (
    <Wrapper>
      { isPending && <LoaderTEXT /> }
      { !isPending && !OS && <Link1 to="/login">Verified Failed! Click to direct back DINO Login.</Link1> }
      {/* failed */}
      { !isPending && OS && isVering && <VerifiedSuc>Verified Successfully!</VerifiedSuc> }
      { !isPending && OS && !isVering && <div></div> }
      {/* successfully */}
    </Wrapper>
  );
}

驗證失敗的話會回傳一個 Link 可以讓使用者回到 DINO Login。成功的話就會進到 VIP 專屬的互動區!

圖片 26.png

【小結】
到這邊網頁的部分就正式結束啦!真的好累天啊,學到了超多新東西,也遇到了無數的困難,總歸還是還行地完成了這個不小的企劃。有很多心得想要講的只是那些話就留給結語吧!接下來幾天我會分享除了我專責的網頁任務內容外,其他在上鏈工程的部分!

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/a111b4f1-23b1-4bdf-868f-c71520cc7714/5d3hkb.jpg

【參考資料】
opensea-js
bignumber
React Router: Declarative Routing for React
React CSS


上一篇
Day 22【Tokens' Owner】你好啊大哥哥,真沒想到你可以到二十三樓來呢!不過就到這裡為止了,接下來由我歐噴系的JS來做你的對手!
下一篇
Day 24【Random Picture Blending in Python】return bool;
系列文
All In One NFT Website Development32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言