Day2. 使用 javascript 建構 DAO

經過上一篇教程,我們現在可以連接到使用者的錢包,這意味著我們現在可以驗證該用戶是否在我們的DAO中。為了加入我們的DAO,使用者將需要一個會員資格NFT,如果他們沒有會員資格NFT,我們會提示他們是否鑄造會員NFT並加入我們的DAO(你也可以自己設計一個比較好的機制,比如常見的白單限制)

要完成以上的需求,我們需要編寫+部署我們自己的NFT智能合約,在這邊我們使用ThirdWeb給我們提供的是一套工具,可以在不編寫任何Solidity的情況下創建我們所有的智能合約(不過使用這種方式會有諸多局限性,如果你對於Solidity很熟悉,之後也可以嘗試自己編寫並部署)

不過我們這系列的都不會使用到Solidity編碼,ThirdWeb提供了一組安全的合同標準,並且在部署之後你也可以使用其用戶端 SDK 輕鬆地從前端與這些合約進行交互

介紹完我們接下來要使用的強力工具,我們可以開嚕了

創建 ThirdWeb 專案

此網站創建專案

  1. 連接含有 Rinkeby ETH 的 Metamask address(部署合約時會需要耗費gas fee)

  2. 連接到 Rinkeby 網路

  3. 點擊右上 Create Project(這將為我們將在鏈上部署的合約創建容器,thirdweb不會有中心化資料庫,你的所有數據都存儲在鏈上

獲取 Alchemy API

Alchemy官網申請帳號,並點擊 +CREATE APP 來創建,NETWORK部分一定要選擇到Rinkeby,創建完成後,點擊 VIEW KEY 可以看到你的 API KEY , HTTP , WEBSOCKETS

post image

.ENV存儲私鑰

現在,我們需要實際編寫一些腳本,讓我們使用thirdweb創建/部署我們的合約到Rinkeby。首先,我們要做的第一件事是在專案的根目錄中創建一個.env

PRIVATE_KEY=YOUR_PRIVATE_KEY_HERE
WALLET_ADDRESS=YOUR_WALLET_ADDRESS
ALCHEMY_API_URL=YOUR_ALCHEMY_API_URL

thirdweb需要所有這些東西來代表你部署合同,它們不存儲任何內容,所有內容都保留在本地的檔中。謹記不要將 .env 檔提交到 Github,你的錢包會被搶劫的,小心!!!

從Metamask獲取所需資訊

點擊【Account details】,再點擊【Export Private Key】,輸入密碼後便可取得 PRIVATE_KEY

點擊Account下方 0x... 後方的複製icon即可取得 WALLET_ADDRESS

從Alchemy獲取 ALCHEMY_API_URL

post image
post image

初始化軟體開發工具組

前往 .scripts/1-initialize-sdk.js

import { ThirdwebSDK } from "@3rdweb/sdk";
import ethers from "ethers";

import dotenv from "dotenv";
dotenv.config();

if (!process.env.PRIVATE_KEY || process.env.PRIVATE_KEY == "") {
  console.log("🛑 Private key not found.")
}

if (!process.env.ALCHEMY_API_URL || process.env.ALCHEMY_API_URL == "") {
  console.log("🛑 Alchemy API URL not found.")
}

if (!process.env.WALLET_ADDRESS || process.env.WALLET_ADDRESS == "") {
  console.log("🛑 Wallet Address not found.")
}

const sdk = new ThirdwebSDK(
  new ethers.Wallet(
    process.env.PRIVATE_KEY,
    ethers.getDefaultProvider(process.env.ALCHEMY_API_URL),
  ),
);

(async () => {
  try {
    const apps = await sdk.getApps();
    console.log("Your app address is:", apps[0].address);
  } catch (err) {
    console.error("Failed to get apps from the sdk", err);
    process.exit(1);
  }
})()

export default sdk;

我們這邊所做的是初始化thirdweb,然後添加一個third web SDK,因為我們將在其他腳本中重用初始化的sdk。在初始化的過程中我們必須提供 PRIVATE_KEY以及使用 ALCHEMY_API_URL 創建的 prvider

在執行該腳本之前,請確保您安裝了Node 16 +,您可以使用以下命令檢查您的版本:

node -v

如果您有舊版本的 Node,可以在此處進行更新。(下載 LTS 版本)

接下來,讓我們來執行這個腳本,移至終端並貼下以下命令:

node scripts/1-initialize-sdk.js

以下是運行完腳本時獲得的內容

buildspace-dao-starter % node scripts/1-initialize-sdk.js
👋 Your app address is: 0xa002D595189bF9D50D5897C64b6e07BE5bdEe9b8

💡 *注意:您可能還會看到一些隨機警告,例如*`ExperimentalWarning`,只需確保您的應用程式位址已列印出來即可!

接著將這段地址加入 .env 檔,你目前的 .env 檔內應該如下:

PRIVATE_KEY=<YOUR_PRIVATE_KEY_HERE>
ALCHEMY_API_URL=<YOUR_ALCHEMY_API_URL>
WALLET_ADDRESS=<YOUR_WALLET_ADDRESS>

APP_MODULE_ADDRESS=0xa002D595189bF9D50D5897C64b6e07BE5bdEe9b8

創建 ERC1155 集合

我們現在要做的是創建+部署ERC1155合約到Rinkeby,這是我們創建NFT所需的基本模組。這邊我們要先為NFT設置元數據**。**這是諸如集合的名稱(例如CryptoPunks)以及與集合關聯的圖像之類的東西,該圖像在OpenSea上顯示為標題。

💡 您可能知道ERC-721,其中每個NFT都是唯一的,即使它們具有相同的圖像,名稱和屬性。使用ERC-1155,多個人可以成為同一NFT的持有者。在這種情況下,我們的"會員NFT"對每個人都是一樣的,因此,與其每次都製作一個新的NFT,我們可以簡單地將相同的NFT分配給所有會員。

移至並新增以下代碼:scripts/2-deploy-drop.js

import { ethers } from "ethers";
import sdk from "./1-initialize-sdk.js";
import { readFileSync } from "fs";

import dotenv from "dotenv";
dotenv.config();

const app = sdk.getAppModule(process.env.APP_MODULE_ADDRESS);

(async () => {
  try {
    const bundleDropModule = await app.deployBundleDropModule({
      name: "DevDAO",
      description: "A DAO for devloper",
      image: readFileSync("scripts/assets/dev.png"),
      primarySaleRecipientAddress: ethers.constants.AddressZero,
    });

    console.log(
      "✅ Successfully deployed bundleDrop module, address:",
      bundleDropModule.address,
    );
    console.log(
      "✅ bundleDrop metadata:",
      await bundleDropModule.getMetadata(),
    );
  } catch (error) {
    console.log("failed to deploy bundleDrop module", error);
  }
})()

我們給集合一個namedescriptionprimarySaleRecipientAddressimage

  • name: DAO 的名稱,請自己隨意命名

  • description: 簡單描述這個 DAO

  • image: 我們會從本地檔載入,因此請確保將該圖像包含在下scripts/assets ,並確保圖片格式是PNG,JPG或GIF

  • primarySaleRecipientAddress: 傳入一個地址,這個地址是用來接收NFT賣出的$,這邊我們將其設定為 ‘0x0’ 也就是 ethers.constants.AddressZero 是為了不向使用者收費,你也可以將地址改為自己的地址來收費

運行此腳本後會看到如下輸出:

node scripts/2-deploy-drop.js
buildspace-dao-starter % node scripts/2-deploy-drop.js
👋 Your app address is: 0xa002D595189bF9D50D5897C64b6e07BE5bdEe9b8
✅ Successfully deployed bundleDrop module, address: 0x31c70F45060AE0870624Dd9D79A1d8dafC095A5d
✅ bundleDrop metadata: {
  metadata: {
    name: 'NarutoDAO Membership',
    description: 'A DAO for fans of Naruto.',
    image: 'https://cloudflare-ipfs.com/ipfs/bafybeicuuhilocc2tskhnvbwjqarsc5k7flfqdr4ifvwxct32vzjmb3sam',
    primary_sale_recipient_address: '0x0000000000000000000000000000000000000000',
    uri: 'ipfs://bafkreieti3mpdd3pytt3v6vxbc3rki2ja6qpbblfznmup2tnw5mghrihnu'
  },
  address: '0x31c70F45060AE0870624Dd9D79A1d8dafC095A5d',
  type: 11
}

首先,我們剛剛向Rinkeby部署了ERC-1155合同,如果你到etherscan並查詢 bundleDrop 的地址(第一行的地址),會發現你成功剛剛部署了一個智能合約!

把這串地址添加到 .env

PRIVATE_KEY=<YOUR_PRIVATE_KEY_HERE>
ALCHEMY_API_URL=<YOUR_ALCHEMY_API_URL>
WALLET_ADDRESS=<YOUR_WALLET_ADDRESS>

APP_MODULE_ADDRESS=0xa002D595189bF9D50D5897C64b6e07BE5bdEe9b8
BUNDLEDROP_MODULE_ADDRESS=0xa002D595189bF9D50D5897C64b6e07BE5bdEe9b8
post image

可以在此處查看thirdweb使用的實際智慧合約代碼

另外,我們可以通過CloudFlare從IPFS檢索NFT的圖像

您甚至可以使用URI直接點擊IPFS(注意 - 由於您需要運行IPFS節點,因此在Chrome上不起作用,但可以在Brave上工作,它可以為您做到這一點

💡 IPFS基本上是一個分散的存儲系統,[請在此處閱讀更多內容](https://docs.ipfs.io/concepts/what-is-ipfs/)!

如果您之前在Solidity中開發了一個自定義智慧合約,也了解其開發過程,相對來說,使用thirdWeb 讓整個流程變得更簡單,目前,我們已經有一個合約部署到IPFS上託管的Rinkeby +數據,恭喜你

接下來,我們需要實際創建我們的NFT Day3. 使用 javascript 建構 DAO