# 手把手教程 ——Alchemy Week4

By [RogerZ](https://paragraph.com/@rogerz-2) · 2022-08-17

---

Alchemy 教程目录
------------

[**Week1: How to Develop an NFT Smart Contract (ERC721) with Alchemy 教程**](https://mirror.xyz/0xF4b64958cF4BB506A24cE5e8b8dB5fd5a0f70315/PWrvfMYu4x-5UVd31BUyEH7toL4XlLvzdpwSKdg_rv8)

[**Week2: How to Build “Buy Me a Coffee“ Defi dapp with Alchemy 教程**](https://mirror.xyz/0xF4b64958cF4BB506A24cE5e8b8dB5fd5a0f70315/DRy4cVDaPNBtxAD-Dxs0h3LPIUkzuo9TDahPfk10hnM)

[**Week3: How to Make NFTs with On-Chain Metadata - Hardhat and JavaScript 教程**](https://mirror.xyz/0xF4b64958cF4BB506A24cE5e8b8dB5fd5a0f70315/SS2cdZvAl-k2XcboQQRteCoTQ4v3Adpr6Pn9oHyQthU)

Week4: How to Create an NFT Gallery 教程
======================================

[官方教程](https://docs.alchemy.com/docs/how-to-create-an-nft-gallery)在此，也可以看 youtube 视频链接，不想看我啰嗦的可以移步。

[![]({{DOMAIN}}/editor/youtube/play.png)](https://www.youtube.com/watch?v=JzsTfOFjC1o)

### step0 环境配置

*   **系统环境：**
    
    Window10 X64
    
*   **编程环境：**
    
    nodeJS v16.15.0
    
    NPM v8.5.5
    
*   **编程IDE：**
    
    VS Code
    

### step1 编辑项目

1\. 在文件夹下，进入 cmd 输入 `npx create-next-app -e with-tailwindcss nftgallery`，nftgallery 可以自行取名。

![](https://storage.googleapis.com/papyrus_images/ddf9b7241637129ff068e7d488a61581cc460940c4252e2be14550cf0f740bee.png)

2\. 进入文件夹后，打开 VS Code，在 cmd 中输入 `npm run dev`。在浏览器中打开 localhost:3000，可以看到原始的页面 。

![](https://storage.googleapis.com/papyrus_images/25d51900783dc2bf4e85aed657ea7be516a540f7e5df2f3ecb9d54e8765bbc41.png)

3\. 修改 ./pages 下的两个文件的后缀名，改为 .jsx

![](https://storage.googleapis.com/papyrus_images/221555ee92524b5cee4e2d49bc725e16c63640b8a721bed27ffa24b8d481dee8.png)

4\. 编辑 ./pages/index.jsx，复制以下代码并保存

    import Head from 'next/head'
    import Image from 'next/image'
    import { useState } from 'react'
    import { NFTCard } from './components/nftCard'
    import { api_key } from '../next-env.d'
    
    
    const Home = () => {
      const [wallet, setWalletAddress] = useState("");
      const [collection, setCollectionAddress] = useState("");
      const [NFTs, setNFTs] = useState([])
      const [fetchForCollection, setFetchForCollection] = useState(false)
    
      const fetchNFTs = async() => {
        let nfts;
        console.log("fetching nfts");
        const api_key = "KQlNfx1NHVyWFC62jMIwysYLUTHprKGe";
        const baseURL = `https://eth-mainnet.alchemyapi.io/v2/${api_key}/getNFTs/`;
    
        if(!collection.length) {
          var requestOptions = {
            method: 'GET'
          };
          const fetchURL = `${baseURL}?owner=${wallet}`;
          nfts = await fetch(fetchURL, requestOptions).then(data => data.json())
        } else {
          console.log("fetching nfts for collection owned by address")
          const fetchURL = `${baseURL}?owner=${wallet}&contractAddresses%5B%5D=${collection}`;
          nfts = await fetch(fetchURL, requestOptions).then(data => data.json())
        }
    
        if(nfts) {
          console.log("nfts:", nfts);
          setNFTs(nfts.ownedNfts)
        }
      }
    
      const fetchNFTsForCollection = async() => {
        if(collection.length) {
          var requestOptions = {
            method: 'GET'
          };
          const baseURL = `https://eth-mainnet.alchemyapi.io/v2/${api_key}/getNFTsForCollection/`;
          const fetchURL = `${baseURL}?contractAddress=${collection}&withMetadata=${"true"}`;
          const nfts = await fetch(fetchURL, requestOptions).then(data => data.json())
          if(nfts) {
            console.log("NFTs in collection:", nfts)
            setNFTs(nfts.nfts)
          }
        }
      }
    
      return(
        <div className="flex flex-col items-center justify-center py-8 gap-y-3">
          <div className="flex flex-col w-full justify-center items-center gap-y-2">
            <input disabled={fetchForCollection} className="w-2/5 bg-slate-100 py-2 px-2 rounded-lg text-gray-800 focus:outline-blue-300 disabled:bg-slate-50 disabled:text-gray-50" onChange={(e)=>{setWalletAddress(e.target.value)}} value={wallet} type={"text"} placeholder="Add your wallet address"></input>
            <input className="w-2/5 bg-slate-100 py-2 px-2 rounded-lg text-gray-800 focus:outline-blue-300 disabled:bg-slate-50 disabled:text-gray-50" onChange={(e)=>{setCollectionAddress(e.target.value)}} value={collection} type={"text"} placeholder="Add the collection address"></input>
            <label className="text-gray-600 "><input onChange={(e)=>{setFetchForCollection(e.target.checked)}} type={ "checkbox" } className="mr-2"></input>Fetch for collection</label>
            <button className={"disabled:bg-slate-500 text-white bg-blue-400 px-4 py-2 mt-3 rounded-sm w-1/5"} onClick={
              () => {
                if(fetchForCollection) {
                  fetchNFTsForCollection()
                } else fetchNFTs()
              }
            }>Let's go! </button>
          </div>
          <div className='flex flex-wrap gap-y-12 mt-4 w-5/6 gap-x-2 justify-center'>
            {
              NFTs.length && NFTs.map(nft => {
                return (
                  <NFTCard nft={nft}></NFTCard>
                )
              })
            }
          </div>
        </div>
      )
    }
    
    export default Home
    

5\. 编辑 ./pages/\_app.jsx，复制以下代码并保存

    import '../styles/globals.css'
    
    function MyApp({ Component, pageProps }) {
      return <Component {...pageProps} />
    }
    
    export default MyApp
    

6\. 在./pages下新建 components文件夹，并新建 nftCards.jsx 文件，复制以下代码并保存

    export const NFTCard = ({ nft }) => {
    
        return (
            <div className="w-1/4 flex flex-col ">
                <div className="rounded-md">
                    <img className="object-cover h-128 w-full rounded-t-md" src={nft.media[0].gateway}></img>
                </div>
                <div className="flex flex-col y-gap-2 px-2 py-3 bg-slate-100 rounded-b-md h-110 ">
                    <div className="">
                        <h2 className="text-xl text-gray-800">{nft.title}</h2>
                        <p className="text-gray-600">{nft.id.tokenId.substr(nft.id.tokenId.length - 4)}</p>
                        <p className="text-gray-600">{`${nft.contract.address.substr(0, 4)}...${nft.contract.address.substr(nft.contract.address.length - 4)}`}</p>
                    </div>             
                </div>
    
                <div className="flex-grow mt-2">
                    <p className="text-gray-600">{nft.descripiton?.substr(0, 150)}</p>
                </div>
                <div className="flex justify-center mb-1">
                    <a target={"_blank"} href={`https://etherscan.io/token/${nft.contract.address}`} className="py-2 px-4 bg-blue-500 w-1/2 text-center rounded-m text-white cursor-pointer">View on etherscan</a>
                </div>
            </div>
        )
    }
    

7\. 将./next-env.d 文件后缀名改为 .js，复制以下代码并保存，此文件在上传 github 时需 ignore，如果不上传 github，本步可以忽略

    module.exports = {
      api_key: "输入你的api_key"
    }
    

### step2 申请 Alchemy 帐号

1\. 注册 alchemy 帐号详细步骤可以回看 week1 教程的 step3。

[https://www.alchemy.com/](https://www.alchemy.com/)

2\. 进入 Dashboard，点击 create app。

![](https://storage.googleapis.com/papyrus_images/23e6facd6f57a3d8c3ecb1f6b9be4bd84fb3e7c5d5da656f98f0726e571e8b22.png)

3\. 依次填入 Name, Description，Chain 选择 Ethereum，Network 选择 Mainnet，然后点击 CREATE APP。

![](https://storage.googleapis.com/papyrus_images/8a7111eda92a0358d6f13aa4da1d5a269fb4e705c383d19180b9f4bb14883bc5.png)

4\. 点击 VIEW KEY，复制 API KEY 的内容并粘贴到 ./next-env.d.js 文件中

![](https://storage.googleapis.com/papyrus_images/5035c58953ffe2ac27e13c36baaab6eab24c57f44ef782033230f9b9fd1cbde1.png)

至此，全部搞定，查看效果图。输入 Azuki 的合约地址。

![](https://storage.googleapis.com/papyrus_images/664abe9b400aecbfd43ff1c9805284cd056e760ac53a44657b002910ae82be33.png)

### step3 在官网提交任务并 claim NFT

在官方申请网址中提交对应的信息。

[https://alchemyapi.typeform.com/roadtoweekfour](https://alchemyapi.typeform.com/roadtoweekfour)

在 mintkudos 网址中 claim Alchemy 的 NFT，通常需要一天至一周可以获得 allowlist 资格。

[https://mintkudos.xyz/claim/853](https://mintkudos.xyz/claim/853)

![](https://storage.googleapis.com/papyrus_images/e3bf92ee2d9e6ea0b5eda23d995eec30aa8b3718b552831dbd1886ffa6531ab1.png)

---

*Originally published on [RogerZ](https://paragraph.com/@rogerz-2/alchemy-week4)*
