前言:
此时看官们对“js教程3”大概比较着重,同学们都需要了解一些“js教程3”的相关文章。那么小编也在网上收集了一些对于“js教程3””的相关文章,希望咱们能喜欢,同学们快快来了解一下吧!目录
开始
• 让我们构建一些很酷的东西。• 什么是 DAO?
为 DAO 设置客户端应用程序
• 获取客户端代码 + 获取设置。• 将“连接到钱包”添加到您的 DAO 仪表板。
创建会员 NFT
• 部署你的 NFT 包。• 部署 NFT 元数据。• 让用户铸造你的 NFT。
创建代币+治理
• 部署 ERC-20 合约。• 在 DAO Dashboard 上展示代币持有者。• ⚖️ 建库+治理。• ✅ 让用户对提案进行投票。
收尾工作
• 删除您的管理员权限并处理基本错误。• 完成并庆祝。 部署你的 NFT 包。 开始使用thirdweb
真棒!我们现在可以连接到用户的钱包,这意味着我们现在可以检查他们是否在我们的 DAO 中!为了加入我们的 DAO,用户需要会员资格 NFT。如果他们没有会员 NFT,我们会提示他们创建会员 NFT 并加入我们的 DAO!
但是,有一个问题。为了让我们铸造 NFT,我们需要编写 + 部署我们自己的 NFT 智能合约。这实际上是thirdWeb 发挥作用的地方。
thirdWeb 为我们提供了一套工具,无需编写任何 Solidity 即可创建我们所有的智能合约。
我们不写 Solidity。我们需要做的就是只使用 JavaScript 编写一个脚本来创建和部署我们的合约。thirdweb 将使用他们在这里[1]创建的一组安全、标准的合约。很酷的部分是在您创建合约之后,您拥有它们并且它们与您的钱包相关联。
部署合约后,您可以使用它们的客户端 SDK 从前端轻松地与这些合约进行交互。
我无法形容与编写你自己的Solidity代码相比,用thirdweb创建一个智能合约是多么容易,它感觉就像与一个普通的后台库互动。让我们开始吧。
thirdweb 仪表板[2]允许我们在不编写任何代码的情况下创建合约,但在本教程中,我们将使用 JavaScript 创建它们。
重要的!thirdweb 没有数据库,您的所有数据都存储在链上。
创建一个运行thirdweb脚本的地方
现在我们需要实际编写一些脚本,让我们使用thirdweb 创建/部署我们的合约到Goerli。我们要做的第一件事是在项目的根目录中创建一个看起来像这样的.env文件。
PRIVATE_KEY=YOUR_PRIVATE_KEY_HEREWALLET_ADDRESS=YOUR_WALLET_ADDRESSQUICKNODE_API_URL=YOUR_QUICKNODE_API_URL
注意:在 Repli?你需要使用这个[3]。基本上,.env 文件在 Replit 上不起作用。您应该使用此方法逐一添加具有相同名称的变量。完成后,您需要通过停止/运行 repo 来启动 Replit,以便它获取新的 env 变量!
thirdweb 需要所有这些东西来代表您部署合同。他们没有存储任何内容,所有内容都保留在本地.env文件中。不要将您的.env文件提交到 Github。你的信息会被盗走。当心。
要从 Metamask 获取您的私钥,请查看此[4]内容。
要获取您的钱包地址,请查看此[5]内容。
快速节点
您在.env文件中需要的最后一件事是QUICKNODE_API_URL.
QuickNode 本质上帮助我们广播我们的合约创建交易,以便它可以尽快被测试网上的矿工拾取。一旦交易被挖掘出来,它就会作为合法交易被广播到区块链上。从那里,每个人都会更新他们的区块链副本。
因此,请在此处[6]使用 QuickNode 注册一个帐户 。
看看下面的视频,看看如何为测试网获得你的API密钥! 不要乱来,创建一个主网密钥,我们需要一个测试网密钥。 查看下面的视频,了解如何获取测试网的 API!
您现在应该在.env文件中包含这三个项目了!
初始化 SDK
前往scripts/1-initialize-sdk.js。
import { ThirdwebSDK } from "@thirdweb-dev/sdk";// Importing and configuring our .env file that we use to securely store our environment variablesimport dotenv from "dotenv";dotenv.config();// Some quick checks to make sure our .env is working.if (!process.env.PRIVATE_KEY || process.env.PRIVATE_KEY === "") { console.log(" Private key not found.");}if (!process.env.QUICKNODE_API_URL || process.env.QUICKNODE_API_URL === "") { console.log(" QuickNode API URL not found.");}if (!process.env.WALLET_ADDRESS || process.env.WALLET_ADDRESS === "") { console.log(" Wallet Address not found.");}const sdk = ThirdwebSDK.fromPrivateKey( // Your wallet private key. ALWAYS KEEP THIS PRIVATE, DO NOT SHARE IT WITH ANYONE, add it to your .env file and do not commit that file to github! process.env.PRIVATE_KEY, // RPC URL, we'll use our QuickNode API URL from our .env file. process.env.QUICKNODE_API_URL)(async () => { try { const address = await sdk.getSigner().getAddress(); console.log(" SDK initialized by address:", address) } catch (err) { console.error("Failed to get apps from the sdk", err); process.exit(1); }})();// We are exporting the initialized thirdweb SDK so that we can use it in our other scriptsexport default sdk;
确保我们的 sdk 初始化正确!
在执行该功能之前,请确保您已安装 Node 16+,您可以使用以下命令检查您的版本:
node -v
注意:如果您在 Replit 上,您实际上可以从它提供的 shell 运行脚本:
如果你有旧版本的 Node,你可以在这里[7]更新它。(下载 LTS 版本)
注意:如果您在 Replit 上,您实际上可以通过从 shell 运行它来更新节点版本:
npm init -y && npm i --save-dev node@17 && npm config set prefix=$(pwd)/node_modules/node && export PATH=$(pwd)/node_modules/node/bin:$PATH
让我们执行它!转到您的终端并粘贴以下命令:
node scripts/1-initialize-sdk.js
这是我运行脚本时得到的结果。
buildspace-dao-starter % node scripts/1-initialize-sdk.js SDK initialized by address: 0xF11D6862e655b5F4e8f62E00471261D2f9c7E380
注意:您可能还会看到一些随机警告,例如ExperimentalWarning,请确保您的应用地址已打印出来!
史诗。如果你看到它打印出你的钱包地址,那么这意味着一切都已初始化!
创建一个 ERC-1155 集合
我们现在要做的是创建 + 部署 ERC-1155 合约到 Goerli。这基本上是我们创建 NFT 所需的基本模块。我们还没有在这里创建我们的 NFT。我们只是围绕集合本身设置元数据。这类似于集合的名称(例如 CryptoPunks)以及与集合相关联的图像,该图像在 OpenSea 上显示为标题。
注意:您可能知道 ERC-721,其中每个 NFT 都是唯一的,即使它们具有相同的图像、名称和属性。使用 ERC-1155,多人可以成为同一个 NFT 的持有者。在这种情况下,我们的“会员 NFT”对每个人都是一样的,所以我们不必每次都创建一个新的 NFT,而可以简单地将相同的 NFT 分配给我们的所有成员。这也更省gas!对于所有持有者的 NFT 相同的情况,这是一种非常常见的方法。
前往scripts/2-deploy-drop.js并添加以下代码:
import { AddressZero } from "@ethersproject/constants";import sdk from "./1-initialize-sdk.js";import { readFileSync } from "fs";(async () => { try { const editionDropAddress = await sdk.deployer.deployEditionDrop({ // The collection's name, ex. CryptoPunks name: "NarutoDAO Membership", // A description for the collection. description: "A DAO for fans of Naruto.", // The image that will be held on our NFT! The fun part :). image: readFileSync("scripts/assets/naruto.png"), // We need to pass in the address of the person who will be receiving the proceeds from sales of nfts in the contract. // We're planning on not charging people for the drop, so we'll pass in the 0x0 address // you can set this to your own wallet address if you want to charge for the drop. primary_sale_recipient: AddressZero, }); // this initialization returns the address of our contract // we use this to initialize the contract on the thirdweb sdk const editionDrop = await sdk.getContract(editionDropAddress, "edition-drop"); // with this, we can get the metadata of our contract const metadata = await editionDrop.metadata.get(); console.log( "✅ Successfully deployed editionDrop contract, address:", editionDropAddress, ); console.log("✅ editionDrop metadata:", metadata); } catch (error) { console.log("failed to deploy editionDrop contract", error); }})();
一个非常简单的脚本!
我们给我们的集合一个name, descriptionand primary_sale_recipient, and image。我们正在从本地文件加载image,因此请务必将该图像包含在scripts/assets. 现在确保它是 PNG、JPG 或 GIF,并确保它是本地图像 - 如果您使用 Internet 链接,这将不起作用!
当我使用 node scripts/2-deploy-drop.js运行它时,我得到了。
buildspace-dao-starter % node scripts/2-deploy-drop.js SDK initialized by address: 0xF11D6862e655b5F4e8f62E00471261D2f9c7E380✅ Successfully deployed editionDrop contract, address: 0xE56fb4F83A9a99E40Af1C7eF08643e7bf1259A95✅ editionDrop metadata: { name: 'NarutoDAO Membership', description: 'A DAO for fans of Naruto.', image: ';, seller_fee_basis_points: 0, fee_recipient: '0x0000000000000000000000000000000000000000', merkle: {}, symbol: ''}
好吧,刚刚发生的事情真是太有意思了。发生了两件事:
一,我们刚刚向 Goerli部署了ERC-1155合约。[8]这是正确的!如果您前往并粘贴editionDrop合约地址,您会看到您刚刚部署了一个智能合约!最酷的部分是你拥有这个合约,它是从你的钱包中部署的。“发件人”地址将是您的公共地址。
注意:请保留您的editionDrop地址,我们稍后需要它!,如果您丢失了它,您可以随时从thirdweb 仪表板中检索找到[9]。
很有史诗感。。一个部署好的,只用javascript的定制合同。您可以在此处查看[10]thirdweb 使用的实际智能合约代码。
我们在这里做的另一件事是 thirdweb 自动上传并将我们收藏的图像固定到 IPFS。您会看到一个以打印出来的链接开头。如果您将其粘贴到浏览器中,您将看到您的 NFT 图像正在通过 CloudFlare 从 IPFS 检索!
你甚至可以直接使用 ipfs:// URI 来访问 IPFS(注意——这不能在 Chrome 上工作,因为你需要运行一个 IPFS 节点,但可以在 Brave 浏览器上为你做到这一点!)
注意:IPFS 基本上是一个去中心化的存储系统,在这里[11]阅读更多信息!
如果您以前在 Solidity 中开发过自定义智能合约,这有点令人兴奋。我们已经将合约部署到 Goerli + IPFS 上托管的数据。狂野。接下来,我们需要实际创建我们的 NFT!
部署 NFT 元数据 设置NFT数据
好的,现在我们要实际部署与我们的会员资格NFT相关的元数据。我们还没有做到这一点。到目前为止,我们所做的就是创建ERC-1155合约,并添加一些基本的元数据。我们还没有实际设置我们的会员制NFT,让我们来做这件事!
前往scripts/3-config-nft.js并添加进去:
import sdk from "./1-initialize-sdk.js";import { readFileSync } from "fs";(async () => { try { const editionDrop = await sdk.getContract("INSERT_EDITION_DROP_ADDRESS", "edition-drop"); await editionDrop.createBatch([ { name: "Leaf Village Headband", description: "This NFT will give you access to NarutoDAO!", image: readFileSync("scripts/assets/headband.png"), }, ]); console.log("✅ Successfully created a new NFT in the drop!"); } catch (error) { console.error("failed to create the new NFT", error); }})();
很简单!
我们要做的第一件事是访问我们的editionDrop合约,它是一个ERC-1155。INSERT_EDITION_DROP_ADDRESS是上一步打印出来的地址。这就是Successfully deployed editionDrop contract, address后面打印出来的地址。 您还可以在您的thirdweb 仪表板上[12]找到它。您的 thirdweb 仪表板将显示您当前正在处理的合同,它还会显示地址,以便您轻松复制和粘贴。
然后,我们在 ERC-1155 上使用createBatch设置我们的实际NFT. 我们需要设置一些属性:
• name:我们 NFT 的名称。• description : 我们 NFT 的描述• image:我们 NFT 的图像。这是用户声称能够访问您的 DAO 的 NFT 的图像。
请记住,因为它是 ERC-1155,所以我们所有的成员都会铸造相同的 NFT。
请务必替换image: readFileSync("scripts/assets/headband.png")为您自己的图像。和以前一样,请确保它是本地图像,因为如果您使用互联网链接,这将不起作用。
我正在建造 NarutoDAO,所以,我的成员需要一个 Leaf Village Headband 才能加入 :
发挥你的创意,不要抄袭!
准备好后,运行:
node scripts/3-config-nft.js
这是我得到的:
SDK initialized by address: 0xF11D6862e655b5F4e8f62E00471261D2f9c7E380✅ Successfully created a new NFT in the drop!设置索赔条件
现在我们需要实际设置我们的“索赔条件”。可以铸造的最大 NFT 数量是多少?用户什么时候可以开始铸造 NFT?同样,这通常是您需要写入合约的自定义逻辑,但在这种情况下,thirdweb 使它变得容易。
前往scripts/4-set-claim-condition.js并添加:
import sdk from "./1-initialize-sdk.js";import { MaxUint256 } from "@ethersproject/constants";(async () => { try { const editionDrop = await sdk.getContract("INSERT_EDITION_DROP_ADDRESS", "edition-drop"); // We define our claim conditions, this is an array of objects because // we can have multiple phases starting at different times if we want to const claimConditions = [{ // When people are gonna be able to start claiming the NFTs (now) startTime: new Date(), // The maximum number of NFTs that can be claimed. maxClaimable: 50_000, // The price of our NFT (free) price: 0, // The amount of NFTs people can claim in one transaction. maxClaimablePerWallet: 1, // We set the wait between transactions to unlimited, which means // people are only allowed to claim once. waitInSeconds: MaxUint256, }] await editionDrop.claimConditions.set("0", claimConditions); console.log("✅ Sucessfully set claim condition!"); } catch (error) { console.error("Failed to set claim condition", error); }})();
这里和以前一样,一定要替换INSERT_EDITION_DROP_ADDRESS为你的 ERC-1155 合约的地址。
startTime是允许用户开始铸造 NFT 的时间,在这种情况下,我们只需将该日期/时间设置为当前时间,这意味着铸造可以立即开始。
maxClaimable是可以铸造的最大成员 NFT 数。
maxClaimablePerWallet指定某人可以在单笔交易中索取多少代币,我们将其设置为1个,因为我们只希望用户一次铸造一个 NFT!在某些情况下,您可能希望一次向您的用户铸造多个 NFT(例如,当他们打开一个包含多个 NFT 的战利品箱时),但在这种情况下,我们只需要1个。
price设置我们 NFT 的价格,在我们的例子中,免费设置为 0。
waitInSeconds是交易之间的时间量,因为我们只希望人们认领一次,我们将其设置为区块链允许的最大数量。
最后,我们这样执行了editionDrop.claimConditions.set("0", claimConditions),这实际上将与我们在链上部署的合约进行交互并调整条件,非常酷!为什么我们要传入 0?好吧,基本上我们的会员 NFT 有一个tokenId为0,因为它是我们 ERC-1155 合约中的第一个代币。请记住——使用 ERC-1155,我们可以让多个人铸造同一个 NFT。在这种情况下,每个人都会铸造一个带有 id 为 0的 NFT。但是,我们也可以有一个不同的 NFT 以及 id为 1,也许我们将 NFT 提供给我们的 DAO 中优秀的成员!这完全取决于我们。
运行后node scripts/4-set-claim-condition.js,我得到:
SDK initialized by address: 0xF11D6862e655b5F4e8f62E00471261D2f9c7E380✅ Successfully set claim condition!
砰!我们已经成功地与我们部署的智能合约进行了交互,并为我们的 NFT 提供了它必须遵循的某些规则!如果您复制粘贴打印在那里的bundle drop地址并在其中搜索,您将在那里看到我们与合同进行交互的证据!
让用户铸造你的 NFT
让我们前往App.jsx,我们现在要做的是
1. 如果我们检测到我们的用户拥有 NFT 会员资格,请向他们展示我们的“DAO 仪表板”屏幕,他们可以在其中对提案进行投票并查看 DAO 相关信息。2. 如果我们检测到用户没有我们的 NFT,我们会给他们一个按钮来铸造一个。
我们开始做吧!我们将首先开发case#1,我们需要检测用户是否拥有我们的 NFT。
检查用户是否拥有会员 NFT
前往App.jsx,将我们的导入更新为:
import { useAddress, ConnectWallet, useContract, useNFTBalance } from '@thirdweb-dev/react';import { useState, useEffect, useMemo } from 'react';
在console.log(" Address:", address);下面,我们将在下面添加:
// Initialize our Edition Drop contract const editionDropAddress = "INSERT_EDITION_DROP_ADDRESS" const { contract: editionDrop } = useContract(editionDropAddress, "edition-drop"); // Hook to check if the user has our NFT const { data: nftBalance } = useNFTBalance(editionDrop, address, "0") const hasClaimedNFT = useMemo(() => { return nftBalance && nftBalance.gt(0) }, [nftBalance]) // ... include all your other code that was already there below.
我们首先初始化我们的editionDrop合约。
我们用useNFTBalance来检查当前连接的账户持有多少 NFT。这实际上将从我们部署的智能合约查询以获取数据。我们为什么要使用"0"?好吧,基本上是因为如果你记得"0"是我们的会员 NFT的tokenId。所以,在这里我们问我们的合约,“嘿,这个用户是否拥有一个 id为"0" 的代币?”。
现在,我们知道了一个用户没有NFT的情况 !让我们创建一个按钮让用户铸造一个。
✨ 建立一个“Mint NFT”按钮
我们开始吧!回到App.jsx。我在添加的行上添加了一些评论:
import { useAddress, ConnectWallet, Web3Button, useContract, useNFTBalance } from '@thirdweb-dev/react';import { useState, useEffect, useMemo } from 'react';const App = () => { // Use the hooks thirdweb give us. const address = useAddress(); console.log(" Address:", address); // Initialize our Edition Drop contract const { contract: editionDrop } = useContract("INSERT_EDITION_DROP_ADDRESS", "edition-drop"); // Hook to check if the user has our NFT const { data: nftBalance } = useNFTBalance(editionDrop, address, "0") const hasClaimedNFT = useMemo(() => { return nftBalance && nftBalance.gt(0) }, [nftBalance]) // This is the case where the user hasn't connected their wallet // to your web app. Let them call connectWallet. if (!address) { return ( <div className="landing"> <h1>Welcome to NarutoDAO</h1> <div className="btn-hero"> <ConnectWallet /> </div> </div> ); } // Render mint nft screen. return ( <div className="mint-nft"> <h1>Mint your free DAO Membership NFT</h1> <div className="btn-hero"> <Web3Button contractAddress={editionDropAddress} action={contract => { contract.erc1155.claim(0, 1) }} onSuccess={() => { console.log(` Successfully Minted! Check it out on OpenSea: {editionDrop.getAddress()}/0`); }} onError={error => { console.error("Failed to mint NFT", error); }} > Mint your NFT (FREE) </Web3Button> </div> </div> );}export default App;
我们正在使用Web3Button创建一个按钮,该按钮将在我们的editionDrop合约上调用我们的claim函数。我们传入 用户的 address, 1是NFT 的铸造amount,以及0是NFT的铸币tokenId。
这将使我们的智能合约产生一个交易,并为用户铸造 NFT。我们还传入onSuccess和onError回调来处理成功和错误情况。
当你真正去铸造 NFT 时,Metamask 会弹出,以便你可以支付 gas。完成铸币后,您应该会在控制台中看到Successfully Minted!,以及 Testnet OpenSea 的链接。我们实际上可以在testnets.opensea.io[13]测试网上看到铸造的 NFT,这非常酷!当您前往您的链接时,您会看到如下内容:
很好!在这里你会看到我的 NFT 有“6 个所有者”。您还会看到它说“您拥有 1”,只要您铸造了一个,您就会看到它!
这是因为我实际上有几个朋友为我铸造了这个NFT来测试它。此外,因为它是 ERC-1155,所以每个人都是同一个 NFT 的所有者。这很酷,而且更省gas。铸造1个 ERC721 的成本为 96,073 gas。铸造 ERC1155 需要 51,935 个 gas。为什么?因为每个人都在共享相同的 NFT 数据。我们不必为每个用户复制新数据。
仅当用户拥有 NFT 时才显示 DAO Dashboard
好的,所以如果你还记得我们需要处理两种情况:
1. 如果我们检测到我们的用户拥有 NFT 会员资格,请向他们展示我们的“DAO 仪表板”屏幕,他们可以在其中对提案进行投票并查看 DAO 相关信息。2. 如果我们检测到用户没有我们的 NFT,我们会给他们一个按钮来铸造一个。
这很容易。渲染 mint nft 屏幕之前,我们需要在App.jsx添加以下内容。
if (!address) { return ( <div className="landing"> <h1>Welcome to NarutoDAO</h1> <div className="btn-hero"> <ConnectWallet /> </div> </div> );}// Add this little piece!if (hasClaimedNFT) { return ( <div className="member-page"> <h1>DAO Member Page</h1> <p>Congratulations on being a member</p> </div> );};
现在,当您刷新页面时,您会看到您位于 DAO 成员页面中。是的!!!如果您断开您的钱包与您的网络应用程序的连接,您将被带到“连接钱包”页面。
最后,如果你连接你的钱包并且没有NFT 会员资格,它会提示你铸造一个。我建议你测试这个案例:
1. 断开您的钱包与您的网络应用程序的连接2. 实际创建一个新帐户[14]
这将为您提供一个新的公共地址,以便您可以有一个新地址来接收 NFT。Metamask 让您拥有任意数量的帐户。
一定要测试所有三种情况!
1. 钱包未连接:1. 钱包已连接,但用户没有会员 NFT:1. 用户拥有会员资格 NFT,因此,向他们展示只有 DAO 成员才能看到的页面:
Github源码:
原文链接:
引用链接
[1] 这里:
[2] thirdweb 仪表板:
[3] 这个:
[4] 此:
[5] 此:
[6] 因此,请在此处:
[7] 在这里:
[8] ERC-1155合约。:
[9] thirdweb 仪表板中检索找到:
[10] 您可以在此处查看:
[11] 这里:
[12] thirdweb 仪表板上:
[13] testnets.opensea.io:
[14] 创建一个新帐户:
标签: #js教程3