Intro
긴 과정이 지나고 드디어 맞이한 프로젝트,, 첫 프로젝트는 유명한 NFT 거래소인 OpenSea 구현이다.
기능부터 디자인까지 다 할 수 있으면 좋지만 시간도 시간이고 처음 프로젝트를 해보는 우리에겐 빠듯하지 않을까 잘해나갈 수 있을까 하는 걱정 반, 누군가와 합을 맞춰 결과물을 만들어내는 기대 반으로 시작했다.
목표
- OpenSea의 프론트와 백엔드 아키텍처를 이해한다.
- OpenSea의 API의 동작 원리를 이해하고 레퍼런스를 참조할 수 있다.
- OpenSea 구현
준비
먼저 OpenSea.io를 살펴보았다.

그리고 구현할 수 있는 것들을 구분해 보았다.
- 브라우저 디자인(상단 바, 메인 등 각각의 컴포넌트, 하단 바 등등)
- MetaMask 연동
- 랜덤 한 NFT 목록 출력
- 연동된 MetaMask 계정의 NFT와 특정한 ERC721의 컨트랙트에서 발행한 NFT 목록 확인
사실상 주어진 시간 안에 전부를 똑같이 구현하기에는 시간이 부족하다고 느껴서 할 수 있는 것들만 하기로 했다.
구현
App.js
<BrowserRouter>
<Nav
setmainaccount={setMainaccount}
setmainweb3={setMainweb3}
login={isLogin}
/>
<Routes>
<Route exact={true} path="/" element={<Home account={mainaccount} />} />
<Route path="/browse" element={<Browse onClickItem={onClickItem} />} />
<Route path="/create" element={<Create account={mainaccount} />} />
<Route
path="/activity"
element={<Activity account={mainaccount} web3={mainweb3} />}
/>
<Route
path="/browse/about"
element={<About clickedItem={clickedItem} />}
/>
<Route path="/mypage" element={<MyPage account={mainaccount} />} />
</Routes>
<Footer />
</BrowserRouter>
- react의 router를 이용하여 각 컴포넌트에 연결
Browser.js
const dataLoad = async () => {
const dataList = await fetch(
'https://api.opensea.io/api/v1/assets?order_direction=desc&offset=0&limit=20',
options
)
.then((response) => response.json())
.catch((err) => console.error(err));
setData(dataList.assets);
};
- 랜덤한 NFT를 목록을 출력하기 위한 코드의 일부
- 목록은 20개로 제한
- OpenSea API를 참고(https://docs.opensea.io/reference/api-overview)
Activity.js
const [newErc721addr, setNewErc721addr] = useState();
const addNewErc721Token = async () => {
const tokenContract = await new web3.eth.Contract(erc721Abi, newErc721addr);
const name = await tokenContract.methods.owner().call();
const symbol = await tokenContract.methods.symbol().call();
const totalSupply = await tokenContract.methods.totalSupply().call();
let arr = [];
for (let i = 1; i <= totalSupply; i++) {
arr.push(i);
}
for (let tokenId of arr) {
let tokenOwner = await tokenContract.methods.ownerOf(tokenId).call();
console.log(tokenOwner, '==?', account);
if (String(tokenOwner).toLowerCase() === account) {
let tokenURI = await tokenContract.methods.tokenURI(tokenId).call();
setErc721list((prevState) => {
return [...prevState, { name, symbol, tokenId, tokenURI }];
});
}
}
};
- 특정한 ERC721 컨트랙트 주소의 NFT 목록을 출력하기 위한 코드의 일부
- 입력받은 컨트랙트 주소는 newErc721addr에 저장 후 abi를 불러온 뒤 토큰 컨트랙트를 생성
- 조건문 for문을 이용하여 소유주와 일치하는 NFT 목록을 출력
Erc721.js
let checkId = []
const [to, setTo] = useState('');
const sendToken = async (tokenAddr, tokenId) => {
const tokenContract = await new web3.eth.Contract(erc721Abi, tokenAddr, {
from: account,
});
if (to !== null) {
tokenContract.methods
.transferFrom(account, to, tokenId)
.send({
from: account,
})
.on('receipt', (receipt) => {
console.log(receipt);
setTo('');
});
}
};
- ERC721 전송을 위한 코드의 일부
- web3 사용
- to에 주소를 저장
- 컨트랙트 주소와 abi로 tokenContract 생성
- transferFrom 함수를 이용하여 전송
시연

회고
일주일이라는 시간이 길다고 생각했는데 생각보다 엄청 짧은 시간이었다. 파트를 나누는 일도 쉽지 않았고 나눈 뒤에 다시 합치는 거도 꽤 쉽지 않았다.. git sjan qhrwkq..
누군가는 이렇게 말했다. '첫 프로젝트의 목표는 성공적으로 망치는 것!' 하지만 고진감래라는 말이 있듯이 좀 부족하지만 우여곡절 끝에 만들어낸 결과물을 보면서 '아.. 이것이 협. 헙. 인가' 하는 생각과 뭔지 모를 감정이 북받쳐 올라왔다. 부족한 실력으로 분석하며 따라가기 바빴고 최대한 열심히 소통하며 사소한 임무일지라도 최선을 다하며 팀에 누가 되지 않도록 노력하는 시간이었다.
앞으로 있을 프로젝트에서도 팀원들과 소통하고 협업하며 멋진 결과물을 만들어 내고 싶고 그 시간 동안 더욱 성장하는 내가 됐으면 좋겠다.
'Hi !' 카테고리의 다른 글
| 클레이튼 개발 환경에서 NFT를 개발해 보자! (0) | 2021.12.13 |
|---|---|
| 니모닉 지갑을 개발해보자! (0) | 2021.12.13 |