[씨냅스Seanapse] (3) 이더리움 네트워크 통신 구현

HY🥗·2022년 6월 17일
1

seanapse

목록 보기
3/4
post-thumbnail

구현 기능

  • Home, MyPage에서 사용할 NFT 목록 조회
  • NFT 상세 정보 조회
    상세 정보 페이지 화면 구현에 시간이 좀 걸려서 내가 맡아 데이터 조회 기능을 구현했다.

Web3.js 이슈

유어클래스 레퍼런스 코드에서는 Web3.js를 사용한 것으로 나와있는데, create-react-app 버전과 관련하여 이슈가 발생했다.

Compiled with problems:X

ERROR in ./node_modules/cipher-base/index.js 3:16-43

Module not found: Error: Can't resolve 'stream' in '/Users/keyesbruh/Documents/Programming/nft-project/node_modules/cipher-base'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
    - add a fallback 'resolve.fallback: { "stream": require.resolve("stream-browserify") }'
    - install 'stream-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
    resolve.fallback: { "stream": false }


ERROR in ./node_modules/eth-lib/lib/bytes.js 9:193-227

Module not found: Error: Can't resolve 'crypto' in '/Users/keyesbruh/Documents/Programming/nft-project/node_modules/eth-lib/lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
    - add a fallback 'resolve.fallback: { "crypto": require.resolve("crypto-browserify") }'
    - install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
    resolve.fallback: { "crypto": false }


ERROR in ./node_modules/web3-eth-accounts/lib/index.js 31:74-91

Module not found: Error: Can't resolve 'crypto' in '/Users/keyesbruh/Documents/Programming/nft-project/node_modules/web3-eth-accounts/lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
    - add a fallback 'resolve.fallback: { "crypto": require.resolve("crypto-browserify") }'
    - install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
    resolve.fallback: { "crypto": false }


ERROR in ./node_modules/web3-eth-accounts/node_modules/eth-lib/lib/bytes.js 7:193-227

Module not found: Error: Can't resolve 'crypto' in '/Users/keyesbruh/Documents/Programming/nft-project/node_modules/web3-eth-accounts/node_modules/eth-lib/lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
    - add a fallback 'resolve.fallback: { "crypto": require.resolve("crypto-browserify") }'
    - install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
    resolve.fallback: { "crypto": false }


ERROR in ./node_modules/web3-providers-http/lib/index.js 30:11-26

Module not found: Error: Can't resolve 'http' in '/Users/keyesbruh/Documents/Programming/nft-project/node_modules/web3-providers-http/lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
    - add a fallback 'resolve.fallback: { "http": require.resolve("stream-http") }'
    - install 'stream-http'
If you don't want to include a polyfill, you can use an empty module like this:
    resolve.fallback: { "http": false }


ERROR in ./node_modules/web3-providers-http/lib/index.js 32:12-28

Module not found: Error: Can't resolve 'https' in '/Users/keyesbruh/Documents/Programming/nft-project/node_modules/web3-providers-http/lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
    - add a fallback 'resolve.fallback: { "https": require.resolve("https-browserify") }'
    - install 'https-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
    resolve.fallback: { "https": false }


ERROR in ./node_modules/xhr2-cookies/dist/xml-http-request.js 37:11-26

Module not found: Error: Can't resolve 'http' in '/Users/keyesbruh/Documents/Programming/nft-project/node_modules/xhr2-cookies/dist'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
    - add a fallback 'resolve.fallback: { "http": require.resolve("stream-http") }'
    - install 'stream-http'
If you don't want to include a polyfill, you can use an empty module like this:
    resolve.fallback: { "http": false }


ERROR in ./node_modules/xhr2-cookies/dist/xml-http-request.js 39:12-28

Module not found: Error: Can't resolve 'https' in '/Users/keyesbruh/Documents/Programming/nft-project/node_modules/xhr2-cookies/dist'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
    - add a fallback 'resolve.fallback: { "https": require.resolve("https-browserify") }'
    - install 'https-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
    resolve.fallback: { "https": false }


ERROR in ./node_modules/xhr2-cookies/dist/xml-http-request.js 41:9-22

Module not found: Error: Can't resolve 'os' in '/Users/keyesbruh/Documents/Programming/nft-project/node_modules/xhr2-cookies/dist'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
    - add a fallback 'resolve.fallback: { "os": require.resolve("os-browserify/browser") }'
    - install 'os-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
    resolve.fallback: { "os": false }

Web3.js 공식 문서를 확인하니 해결 방법을 제안하고 있었다. (https://github.com/ChainSafe/web3.js#troubleshooting-and-known-issues)
하지만 해결 방법을 리서치하던 중 Ethers.js의 점유율이 더 높고, 학습하는 기회로 삼아 Ethers.js를 사용해보자는 의견이 나와 Web3.js 대신 Ethers.js를 사용하였다.
Ethers.js를 사용해본 적이 없어 구글링과 공식 문서를 참고했다. (https://docs.ethers.io/v5/)

코드

import { ethers } from 'ethers';

import seanapseNftAbi from './SeanapseNFT.json'

const SEANAPSE_NFT_CONTRACT_ADDRESS = '0xe18585AE18ea624E361f71BE760DFA1050baaA99'

async function getNftList() {
  // 윈도우 이더리움 객체로 provider 객체 생성
    const provider = new ethers.providers.Web3Provider(window.ethereum); 
  // 발행된 컨트랙트 조회
    let contract = new ethers.Contract(SEANAPSE_NFT_CONTRACT_ADDRESS, seanapseNftAbi, provider);
  // NFT 컨트랙트에서 발행된 NFT 갯수 조회
    let totalSupply = await contract.totalSupply()

    if(totalSupply === 0) {
        return null
    }

    let arr = []
    for (let i = 1; i <= totalSupply; i++) {
      arr.push(i)
    }

    let nftList = []
    for(let tokenId of arr) {
      // 토큰 아이디로 토큰 오너 조회
        let owner = await contract.ownerOf(tokenId)
        // 토큰 아이디로 tokenURI 조회
        let tokenURI =  await contract.tokenURI(tokenId)
        // CID로 <img> src에 넣어서 조회할 수 있는 URL 생성
        fetch("https://ipfs.io/ipfs/" + tokenURI.substr(7))
        .then(res=> res.json())
        .then(out => {
            let name = out.name
            let image = out.image
            nftList.push({name, image, tokenId, owner})
        })
        if(tokenId === arr.length) {
            return nftList
        }
    }
}

// token ID fh 로 상세 정보 조회
async function getNft(tokenId) {
    const provider = new ethers.providers.Web3Provider(window.ethereum); 
    let contract = new ethers.Contract(SEANAPSE_NFT_CONTRACT_ADDRESS, seanapseNftAbi, provider);
    let owner = await contract.ownerOf(tokenId)
    let tokenURI =  await contract.tokenURI(tokenId)
    let network = await provider.getNetwork(1); // 현재 네트워크를 확인할 수 있다.
    fetch("https://ipfs.io/ipfs/" + tokenURI.substr(7))
    .then(res=> res.json())
    .then(out => {
        let imagePath = "https://ipfs.io/ipfs/" + (out.image).substr(7)
        let nftInfo = {
          // 상세 정보 페이지에서 필요한 데이터
            "owner": owner
            , "name": out.name
            , "image": imagePath
            , "description": out.description
            , "attributes": out.attributes
            , "contract":  SEANAPSE_NFT_CONTRACT_ADDRESS
            , "standard": "ERC-721"
            , "network": network.name
        }
        return nftInfo
    })
}

export {getNftList, connectWallet, createNFT, getNft};
profile
사실은 공부를 비밀스럽게 하고 싶었다

0개의 댓글