# 百亿项目Alchemy Road to Web3 第二周NFT获取教程

By [Web3Study](https://paragraph.com/@rabbitverse) · 2023-03-19

---

Alchemy是什么项目？
-------------

2019年12月，Alchemy完成**1500万美元A轮融资**，资方为Pantera Capital，斯坦福大学，Coinbase，三星等。

2021年4月，Alchemy以5.05亿美元估值完成**8000万美元B轮融资**，Coatue和Addition领投，DFJ Growth、K5 Global、Chainsmokers（烟鬼组合）、演员Jared Leto和Glazer家族参投。

2021年10月，Alchemy以35亿美元估值完成**2.5亿美元C轮融资**，由a16z领投的。

2022年2月，Alchemy以102亿美元估值完成**2亿美元融资**，Lightspeed与Silver Lake领投。

**Alchemy是一个**背景强大、经费充足、踏实做事、没有发币的团队，这样的项目不刷，难道去刷土狗吗？

并且，Alchemy计划将新资金用于推广Web3采用，这方面的一些举措包括推出Web3 University，就是现在的 Road to Web3 活动，活动为期10周，每周一个NFT。看了下nft数量极少，估计由于任务难度大，很多小伙伴直接放弃，这样的项目若是空投，绝对是大毛。

手把手第二周教程开始：如何构建“给我买杯咖啡”的 DeFi dapp
----------------------------------

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

官方原版[教程链接](https://docs.alchemy.com/docs/how-to-build-buy-me-a-coffee-defi-dapp)，其中有长达1小时30分钟的视频教程还有大篇幅的文字教程，并且有错误。我按照我的做法给大家一个易于操作的图文教程。

### step1 安装环境

[2022最新Nodejs下载安装配置步骤（保姆级教程）](https://blog.csdn.net/Lancelot38/article/details/125887397)

先按照上述教程安装Nodejs，共分为5步，前3步做完就正常了，我没有做第4和第5步，不放心可以做一下。最新版本号如下：

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

### step2 对 BuyMeACoffee.sol 智能合约进行编码

1.按win+R调出命令框，输入cmd，进入控制台。

2.输入mkdir BuyMeACoffee-contracts按回车创建文件夹，再输入cd BuyMeACoffee-contracts 按回车进入该文件夹。

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

3.输入npm init -y 开始新项目。

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

4.输入npx hardhat创建示例项目。

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

5.之后连按三下回车，出现下图。

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

6.按照提示输入下面代码，坐等安装完毕。出现警告不管。

npm install --save-dev "hardhat@^2.10.1" "@nomicfoundation/hardhat-toolbox@^1.0.1"

7.打开vscode，点击file，点击open folder。找到刚才创建的BuyMeACoffee-contracts文件夹，点击选择文件夹打开

10.右键rename将合约文件lock.sol重命名为 `BuyMeACoffee.sol`

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

11.`BuyMeACoffee.sol`代码替换成下面的并保存！

    //SPDX-License-Identifier: Unlicense
    
    // contracts/BuyMeACoffee.sol
    pragma solidity ^0.8.0;
    
    // Switch this to your own contract address once deployed, for bookkeeping!
    // Example Contract Address on Goerli: 0xDBa03676a2fBb6711CB652beF5B7416A53c1421D
    
    contract BuyMeACoffee {
        // Event to emit when a Memo is created.
        event NewMemo(
            address indexed from,
            uint256 timestamp,
            string name,
            string message
        );
        
        // Memo struct.
        struct Memo {
            address from;
            uint256 timestamp;
            string name;
            string message;
        }
        
        // Address of contract deployer. Marked payable so that
        // we can withdraw to this address later.
        address payable owner;
    
        // List of all memos received from coffee purchases.
        Memo[] memos;
    
        constructor() {
            // Store the address of the deployer as a payable address.
            // When we withdraw funds, we'll withdraw here.
            owner = payable(msg.sender);
        }
    
        /**
         * @dev fetches all stored memos
         */
        function getMemos() public view returns (Memo[] memory) {
            return memos;
        }
    
        /**
         * @dev buy a coffee for owner (sends an ETH tip and leaves a memo)
         * @param _name name of the coffee purchaser
         * @param _message a nice message from the purchaser
         */
        function buyCoffee(string memory _name, string memory _message) public payable {
            // Must accept more than 0 ETH for a coffee.
            require(msg.value > 0, "can't buy coffee for free!");
    
            // Add the memo to storage!
            memos.push(Memo(
                msg.sender,
                block.timestamp,
                _name,
                _message
            ));
    
            // Emit a NewMemo event with details about the memo.
            emit NewMemo(
                msg.sender,
                block.timestamp,
                _name,
                _message
            );
        }
    
        /**
         * @dev send the entire balance stored in this contract to the owner
         */
        function withdrawTips() public {
            require(owner.send(address(this).balance));
        }
    }
    

### step3 创建一个 buy-coffee.js 脚本来测试你的合约

1.将deploy.js重命名为`buy-coffee.js`

并将代码替换成下面的：

    const hre = require("hardhat");
    
    // Returns the Ether balance of a given address.
    async function getBalance(address) {
      const balanceBigInt = await hre.ethers.provider.getBalance(address);
      return hre.ethers.utils.formatEther(balanceBigInt);
    }
    
    // Logs the Ether balances for a list of addresses.
    async function printBalances(addresses) {
      let idx = 0;
      for (const address of addresses) {
        console.log(`Address ${idx} balance: `, await getBalance(address));
        idx ++;
      }
    }
    
    // Logs the memos stored on-chain from coffee purchases.
    async function printMemos(memos) {
      for (const memo of memos) {
        const timestamp = memo.timestamp;
        const tipper = memo.name;
        const tipperAddress = memo.from;
        const message = memo.message;
        console.log(`At ${timestamp}, ${tipper} (${tipperAddress}) said: "${message}"`);
      }
    }
    
    async function main() {
      // Get the example accounts we'll be working with.
      const [owner, tipper, tipper2, tipper3] = await hre.ethers.getSigners();
    
      // We get the contract to deploy.
      const BuyMeACoffee = await hre.ethers.getContractFactory("BuyMeACoffee");
      const buyMeACoffee = await BuyMeACoffee.deploy();
    
      // Deploy the contract.
      await buyMeACoffee.deployed();
      console.log("BuyMeACoffee deployed to:", buyMeACoffee.address);
    
      // Check balances before the coffee purchase.
      const addresses = [owner.address, tipper.address, buyMeACoffee.address];
      console.log("== start ==");
      await printBalances(addresses);
    
      // Buy the owner a few coffees.
      const tip = {value: hre.ethers.utils.parseEther("1")};
      await buyMeACoffee.connect(tipper).buyCoffee("Carolina", "You're the best!", tip);
      await buyMeACoffee.connect(tipper2).buyCoffee("Vitto", "Amazing teacher", tip);
      await buyMeACoffee.connect(tipper3).buyCoffee("Kay", "I love my Proof of Knowledge", tip);
    
      // Check balances after the coffee purchase.
      console.log("== bought coffee ==");
      await printBalances(addresses);
    
      // Withdraw.
      await buyMeACoffee.connect(owner).withdrawTips();
    
      // Check balances after withdrawal.
      console.log("== withdrawTips ==");
      await printBalances(addresses);
    
      // Check out the memos.
      console.log("== memos ==");
      const memos = await buyMeACoffee.getMemos();
      printMemos(memos);
    }
    
    // We recommend this pattern to be able to use async/await everywhere
    // and properly handle errors.
    main()
      .then(() => process.exit(0))
      .catch((error) => {
        console.error(error);
        process.exit(1);
      });
    

如果你粘贴的是官网的，记得把第五行那个位置换成ethers！！！（如下图所示）

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

2.在控制台输入npx hardhat run scripts/buy-coffee.js，出现下图就对了。

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

### step4 使用 Alchemy 和 MetaMask 将您的 BuyMeACoffe.sol 智能合约部署到以太坊 Goerli 测试网

1.右键点击scipts，点击new file，创建一个名为deploy.js的文件。

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

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

2.在deploy.js中粘贴以下代码。

    // scripts/deploy.js
    
    const hre = require("hardhat");
    
    async function main() {
      // We get the contract to deploy.
      const BuyMeACoffee = await hre.ethers.getContractFactory("BuyMeACoffee");
      const buyMeACoffee = await BuyMeACoffee.deploy();
    
      await buyMeACoffee.deployed();
    
      console.log("BuyMeACoffee deployed to:", buyMeACoffee.address);
    }
    
    // We recommend this pattern to be able to use async/await everywhere
    // and properly handle errors.
    main()
      .then(() => process.exit(0))
      .catch((error) => {
        console.error(error);
        process.exit(1);
      });
    

3.在控制台输入npx hardhat run scripts/deploy.js ，并按回车，出现下面那句BuyMeACoffee deployed to: 0x5FbDB2315678afecb367f032d93F642f64180aa3就对了。

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

4.打开你的 `hardhat.config.js`文件，您将看到一些示例部署代码。 删除它并将此版本粘贴到其中。记得保存。

    // hardhat.config.js
    
    require("@nomiclabs/hardhat-ethers");
    require("@nomiclabs/hardhat-waffle");
    require("dotenv").config()
    
    // You need to export an object to set up your config
    // Go to https://hardhat.org/config/ to learn more
    
    const GOERLI_URL = process.env.GOERLI_URL;
    const PRIVATE_KEY = process.env.PRIVATE_KEY;
    
    /**
     * @type import('hardhat/config').HardhatUserConfig
     */
    module.exports = {
      solidity: "0.8.4",
      networks: {
        goerli: {
          url: GOERLI_URL,
          accounts: [PRIVATE_KEY]
        }
      }
    };
    

5.在控制台输入npm install dotenv，安装dotenv。如图所示。

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

6.在控制台输入echo test>.env 创建一个.env文件

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

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

7.将以下代码粘贴进.env

    GOERLI_URL=https://eth-goerli.alchemyapi.io/v2/<your api key>
    GOERLI_API_KEY=<your api key>
    PRIVATE_KEY=<your metamask api key>
    
    8.替换GOERLI_URL。
    
    注册一个 Alchemy帐户。进入dashboard，点击create app。
    

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

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

点击view key

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

复制HTTPS的框内内容，切换到vscode，粘贴到如下位置。

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

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

9.替换GOERLI\_API\_KEY。

将API KEY框内内容复制，然后切换到vscode粘贴到如下位置。

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

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

10.替换PRIVATE\_KEY。

点击metamask右上角三个点，然后点击账户详情。

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

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

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

粘贴到这里，然后保存。

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

11.访问 [https://www.goerlifaucet.com](https://www.goerlifaucet.com/) 并使用您的 Alchemy 帐户登录以获得一些免费的测试以太币。

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

12.运行部署脚本npx hardhat run scripts/deploy.js --network goerli ，发现报错，把缺的这个装上去就好了，见13步。

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

13.直接输入npm install --save-dev @nomiclabs/hardhat-waffle 安装第11步的缺的包。安装时有一堆warn不需要管。

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

14.再运行npx hardhat run scripts/deploy.js --network goerli ，出现下面那行BuyMeACoffee deployed to: 某个地址（**这个地址记得复制粘贴下来**）就对了。

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

### step5 实施一个withdraw脚本

1.右键点击script创建withdraw.js文件，将下列代码粘贴进去。

    // scripts/withdraw.js
    
    const hre = require("hardhat");
    const abi = require("../artifacts/contracts/BuyMeACoffee.sol/BuyMeACoffee.json");
    
    async function getBalance(provider, address) {
      const balanceBigInt = await provider.getBalance(address);
      return hre.ethers.utils.formatEther(balanceBigInt);
    }
    
    async function main() {
      // Get the contract that has been deployed to Goerli.
      const contractAddress="0xDBa03676a2fBb6711CB652beF5B7416A53c1421D";
      const contractABI = abi.abi;
    
      // Get the node connection and wallet connection.
      const provider = new hre.ethers.providers.AlchemyProvider("goerli", process.env.GOERLI_API_KEY);
    
      // Ensure that signer is the SAME address as the original contract deployer,
      // or else this script will fail with an error.
      const signer = new hre.ethers.Wallet(process.env.PRIVATE_KEY, provider);
    
      // Instantiate connected contract.
      const buyMeACoffee = new hre.ethers.Contract(contractAddress, contractABI, signer);
    
      // Check starting balances.
      console.log("current balance of owner: ", await getBalance(provider, signer.address), "ETH");
      const contractBalance = await getBalance(provider, buyMeACoffee.address);
      console.log("current balance of contract: ", await getBalance(provider, buyMeACoffee.address), "ETH");
    
      // Withdraw funds if there are funds to withdraw.
      if (contractBalance !== "0.0") {
        console.log("withdrawing funds..")
        const withdrawTxn = await buyMeACoffee.withdrawTips();
        await withdrawTxn.wait();
      } else {
        console.log("no funds to withdraw!");
      }
    
      // Check ending balance.
      console.log("current balance of owner: ", await getBalance(provider, signer.address), "ETH");
    }
    
    // We recommend this pattern to be able to use async/await everywhere
    // and properly handle errors.
    main()
      .then(() => process.exit(0))
      .catch((error) => {
        console.error(error);
        process.exit(1);
      });
    

2.在控制台输入npx hardhat run scripts/withdraw.js ,运行后如下图就行。

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

### step6 使用 Replit 和 Ethers.js 构建前端 Buy Me A Coffee 网站 dapp

1.在此处访问官方示例项目，并创建您自己的副本以进行修改： [官方示例项目](https://replit.com/@thatguyintech/BuyMeACoffee-Solidity-DeFi-Tipping-app)

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

2.点击fork repl。

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

3.进入该界面，没用过replit的要注册一下。

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

4.下面那一串合约地址换成你在step4 的第14步得到的BuyMeACoffee deployed to:冒号后面的地址。

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

5.在 pages/index.js 中按ctrl+f将名称字符串更新为您自己的名称。

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

6.点击run，出现如图所示即可。

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

7.点击publish。

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

8.一直点下一步，最后publish即可。

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

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

9.进入自己创建的网站试着几笔打赏就可以了。

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

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

### step7 项目提交。

提交[链接](https://alchemyapi.typeform.com/roadtoweektwo)。

注意，最后一步提交内容为

step4 第14步的地址;

step6第8步最后一张图的链接；

你自己的replit主页链接。

### step8 领取NFT。

领取[链接](https://mintkudos.xyz/claim/611)。

---

*Originally published on [Web3Study](https://paragraph.com/@rabbitverse/alchemy-road-to-web3-nft)*
