如何使用 Candy Machine V3 和 TypeScript 创建 Solana NFT 合集

本文详细介绍了如何利用Metaplex JS SDK在Solana区块链上使用Candy Machine V3部署NFT合集。指南涵盖了创建Candy Machine、向其添加NFT项目、实施Candy Guards以设定铸造规则(如开始日期、SOL支付和铸造数量限制),以及最终通过代码铸造NFT的全过程。

Candy Machine V3 已废弃

本指南使用的是不再维护的 Metaplex JS SDK 旧版本。对于新的 NFT 项目,推荐的路径是 如何使用 Metaplex Core Candy Machine 启动 NFT 合集。本指南仅用于历史教育目的。

概述

准备好在 Solana 上推出你的 NFT 合集了吗?如果是,那么你来对地方了!我们将探索 Metaplex 新的 JS SDK,它将 Candy Machine 的强大功能引入你的 JavaScript 和 TypeScript 应用程序,以实现快速简便的铸造。Metaplex 添加了几个新功能,特别是 Candy Guards(一种限制或管理 NFT 铸造访问的工具),我们将在本指南中实现它们。

你将做什么

在本指南中,你将通过你自己的 TypeScript 应用程序创建一个新的 V3 Candy Machine。具体来说,你将:

  1. 创建一个 Candy Machine
  2. 向 Candy Machine 添加项目
  3. 为你的 Candy Machine 实现 Candy Guard
  4. 铸造一个 NFT!

你将需要什么

设置你的项目

在你的终端中创建一个新的项目目录,如下所示:

mkdir cm-v3-demo
cd cm-v3-demo

为你的应用程序创建一个文件 app.ts

echo > app.ts

使用“yes”标志初始化你的项目,以使用新包的默认值:

yarn init --yes
#或者
npm init --yes

创建一个启用了 .json 导入的 tsconfig.json

tsc -init --resolveJsonModule true

安装 Solana Web3 依赖项

我们将需要为本练习添加 Solana Web3 和 SPL Token 库。此外,我们将使用 Metaplex 的 JS SDK。在你的终端中,输入:

yarn add @solana/web3.js@1 @metaplex-foundation/js
#或者
npm install @solana/web3.js@1 @metaplex-foundation/js

添加你的钱包并空投 SOL

在你选择的代码编辑器中打开 cm-v3-demo 目录(我们使用的是 VSCode)。要遵循本指南,你将需要与你的 NFT 授权方相同的 Solana 文件系统钱包。你需要将此钱包存储在项目目录中的一个文件 guideSecret.json 中。

如果你没有纸钱包,可以使用 此脚本 创建一个新钱包。请确保将你的钱包保存到项目目录中,文件名为 guideSecret.json

对于现有钱包,你可以使用下面的空投小部件向其发送一些 Devnet SOL:

🪂 请求 Devnet SOL

注意:过于频繁地发送空投请求可能会触发 429(请求过多)错误。

空投 1 SOL (Devnet)

设置完成后,你的环境应该如下所示:

设置你的应用程序

导入必要的依赖项

打开 app.ts,并将以下导入粘贴到第 1 行

import { Connection, Keypair, PublicKey } from "@solana/web3.js";
import { Metaplex, keypairIdentity, bundlrStorage, toMetaplexFile, toBigNumber, CreateCandyMachineInput, DefaultCandyGuardSettings, CandyMachineItem, toDateTime, sol, TransactionBuilder, CreateCandyMachineBuilderContext } from "@metaplex-foundation/js";
import secret from './guideSecret.json';

除了我们在上一步中创建的钱包之外,我们还从 Solana Web3 和 Metaplex JS 库中导入了一些基本的方法和类。

设置你的 Quicknode 端点

要在 Solana 上构建,你需要一个 API 端点来连接到网络。你可以随意使用公共节点,或者部署和管理你自己的基础设施;但是,如果你想要 8 倍更快的响应时间,可以将繁重的工作交给我们。

查看超过 50% 的 Solana 项目选择 Quicknode 的原因,并在此处注册一个帐户:https://www.quicknode.com/signup?utm_source=internal&utm_campaign=guides&utm_content=how-to-create-a-solana-nft-collection-using-candy-machine-v3-and-typescript。我们将使用 Solana Devnet 节点。

复制 HTTP Provider 链接:

app.ts 中,你的导入语句下方,声明你的 RPC 并建立到 Solana 的连接

const QUICKNODE_RPC = 'https://example.solana-devnet.quiknode.pro/0123456/'; // 👈 替换为你的 Quicknode Solana Devnet HTTP 端点
const SOLANA_CONNECTION = new Connection(QUICKNODE_RPC, { commitment: 'finalized' });

声明变量

你需要声明更多变量来运行你的脚本:

  • 你的源钱包(从你的私钥派生的密钥对)。
  • 源 NFT 元数据 URL(注意:在本指南中,我们将专注于 Candy Machine 的机制,因此我们将重用已上传的 NFT 元数据和图像。欢迎你将图像和元数据上传纳入此练习——有关使用 Metaplex JS SDK 上传到 Arweave 的更多信息,请查看我们关于 如何使用 TypeScript 在 Solana 上铸造 NFT 的指南)。
  • 你希望用作你的合集 NFT 的 NFT 的铸造地址(这是你可能在钱包或交易所中看到的合集封面图像。更多信息请访问 Metaplex.com)。
  • 你的 Candy Machine ID 的占位符(我们稍后会更新它)。
  • 一个 Metaplex 实例。

SOLANA_CONNECTION 下方添加以下声明,以建立我们将使用的钱包以及 NFT 元数据和 Candy Machine ID 的占位符:

const WALLET = Keypair.fromSecretKey(new Uint8Array(secret));
const NFT_METADATA = 'https://mfp2m2qzszjbowdjl2vofmto5aq6rtlfilkcqdtx2nskls2gnnsa.arweave.net/YV-mahmWUhdYaV6q4rJu6CHozWVC1CgOd9NkpctGa2Q';
const COLLECTION_NFT_MINT = '';
const CANDY_MACHINE_ID = '';

通过在 Metaplex.make() 中调用我们的 SOLANA_CONNECTION 来建立一个新的 Metaplex 实例。我们的实例将使用我们刚刚创建的 Keypair:

const METAPLEX = Metaplex.make(SOLANA_CONNECTION)
    .use(keypairIdentity(WALLET));

通过包含我们的网络连接和钱包,API 将使我们能够轻松地向 Solana 网络提交交易。

注意:如果你打算上传自己的图像和元数据(本演示不需要),则需要为存储路由额外包含一个 .use() 调用:

    .use(bundlrStorage({
        address: 'https://devnet.bundlr.network',
        providerUrl: QUICKNODE_RPC,
        timeout: 60000,
    }))

创建合集 NFT

Candy Machine 利用 Metaplex 认证合集 功能来验证链上合集。验证使得第三方(例如交易所)可以轻松地对 NFT 集进行分组和跟踪,并防止假冒。要创建我们的 Candy Machine,我们必须首先创建一个合集 NFT。这将作为你可能在交易所或钱包(例如 Magic Eden 或 Phantom)上看到的“封面图像”。

我们只需要使用 nfts().create() 创建一个新的 NFT。创建一个新函数 createCollectionNft

async function createCollectionNft() {
    const { nft: collectionNft } = await METAPLEX.nfts().create({
        name: "Quicknode Demo NFT Collection",
        uri: NFT_METADATA,
        sellerFeeBasisPoints: 0,
        isCollection: true,
        updateAuthority: WALLET,
      });

      console.log(`✅ - Minted Collection NFT: ${collectionNft.address.toString()}`);
      console.log(`     https://explorer.solana.com/address/${collectionNft.address.toString()}?cluster=devnet`);
}

确保将 isCollection 设置为 true,因为这将表明此 NFT 用于定义合集。

铸造你的 NFT。在应用程序的末尾,调用 createCollectionNft()

createCollectionNft();

然后,在你的终端中运行:

ts-node app

复制 MINT ID 并更新你的 COLLECTION_NFT_MINT 变量(对我们来说在第 11 行):

const COLLECTION_NFT_MINT = 'GWWhaWp7kJ3WKLkQTKyy5DEEGGF4TnCfHXXKxsBSbcwg';

在继续之前,请删除或注释掉对 createCollectionNft() 的调用,因为我们不再需要它。

初始化 Candy Machine

Metaplex SDK 允许你用一行代码初始化 Candy Machine 🤯:

const { candyMachine } = await METAPLEX.candyMachines().create(candyMachineSettings);

然而,如你所见,我们必须首先为我们的 Candy Machine 设置一些参数。创建一个新函数 generateCandyMachine,我们将在其中定义 Candy Machine 设置,然后调用 candyMachines().create()

async function generateCandyMachine() {
    const candyMachineSettings: CreateCandyMachineInput<DefaultCandyGuardSettings> =
        {
            itemsAvailable: toBigNumber(3), // 合集大小:3
            sellerFeeBasisPoints: 1000, // 合集版税:10%
            symbol: "DEMO",
            maxEditionSupply: toBigNumber(0), // 不允许复制每个 NFT
            isMutable: true,
            creators: [\
                { address: WALLET.publicKey, share: 100 },\
            ],
            collection: {
                address: new PublicKey(COLLECTION_NFT_MINT), // 可以替换为你自己的 NFT 或上传新的
                updateAuthority: WALLET,
            },
        };
    const { candyMachine } = await METAPLEX.candyMachines().create(candyMachineSettings);
    console.log(`✅ - Created Candy Machine: ${candyMachine.address.toString()}`);
    console.log(`     https://explorer.solana.com/address/${candyMachine.address.toString()}?cluster=devnet`);
}

Candy Machine 设置定义了合集的大小以及每个 NFT 都相同的关键数据点(例如版税、创作者、符号、可变性)。我们为此示例定义了一些值——你可以随意稍微修改它们以满足你自己的需求。Candy Machine 设置的详细概述可在 Metaplex.com 上找到。请注意,你可以在此步骤中包含 Candy Guards——我们将在下一步中单独添加它们,以便你了解如何更新 Candy Machine 的过程。

继续并初始化你的 Candy Machine。在应用程序的末尾,调用 generateCandyMachine()

generateCandyMachine();

然后,在你的终端中运行:

ts-node app

你应该会看到一个 Candy Machine ID 及其在 Solana Explorer 上的链接:

复制 Candy Machine ID 并更新你的 CANDY_MACHINE_ID 变量(对我们来说在第 11 行):

const CANDY_MACHINE_ID = 'D2ARG7rXosZfnZwVBx3v7piG3H2tcYvWyw5YJCPuEpBU';

如果你遇到错误或有疑问,请在 Discord 上联系我们,我们将很乐意提供帮助。

在继续之前,请删除或注释掉对 generateCandyMachine() 的调用,因为我们不再需要它。

添加 Candy Guards

Candy Machine V3 包含一个名为“Candy Guards”(简称 Guards)的巧妙新功能。Guards 是模块化的代码片段,可以限制对 Candy Machine 铸造的访问,甚至为其添加新功能! (来源:Metaplex.com)。截至 2022 年 11 月,Metaplex 提供了 16 种不同的 Guards:

  • 地址门禁:将铸造限制为单个地址。
  • 白名单:使用钱包地址列表来确定谁被允许铸造。
  • 机器人税:可配置的费用,用于收取无效交易。
  • 结束日期:确定铸造结束的日期。
  • 看门人:通过 Gatekeeper 网络限制铸造,例如 Captcha 集成。
  • 铸造限制:指定每个钱包的铸造数量限制。
  • NFT 销毁:限制铸造给指定合集的持有者,需要销毁 NFT。
  • NFT 门禁:限制铸造给指定合集的持有者。
  • NFT 支付:将铸造价格设置为指定合集中的一个 NFT。
  • 已兑换数量:根据已铸造的总数量确定铸造的结束。
  • SOL 支付:将铸造价格设置为 SOL。
  • 开始日期:确定铸造的开始日期。
  • 第三方签名者:需要交易的额外签名者。
  • Token 销毁:限制铸造给指定 Token 的持有者,需要销毁 Token。
  • Token 门禁:限制铸造给指定 Token 的持有者。
  • Token 支付:将铸造价格设置为 Token 数量。 (来源:Metaplex.com

Metaplex 允许你混合、匹配和堆叠多个 Guards 来定制你的 NFT 铸造。你甚至可以创建各种“Guard Groups”来为不同的用户创建自定义铸造体验。

对于我们的铸造,我们将设置一个开始日期、一个 SOL 支付,以及每个用户 2 次铸造的限制。创建一个新函数 updateCandyMachine()

async function updateCandyMachine() {
    const candyMachine = await METAPLEX
        .candyMachines()
        .findByAddress({ address: new PublicKey(CANDY_MACHINE_ID) });

    const { response } = await METAPLEX.candyMachines().update({
        candyMachine,
        guards: {
            startDate: { date: toDateTime("2022-10-17T16:00:00Z") },
            mintLimit: {
                id: 1,
                limit: 2,
            },
            solPayment: {
                amount: sol(0.1),
                destination: METAPLEX.identity().publicKey,
            },
        }
    })

    console.log(`✅ - Updated Candy Machine: ${CANDY_MACHINE_ID}`);
    console.log(`     https://explorer.solana.com/tx/${response.signature}?cluster=devnet`);
}

我们的函数做了三件事:

  1. 获取我们的 Candy Machine:通过 ID 查找我们的 Candy Machine,并通过调用 .candyMachines().findByAddress() 返回一个 CandyMachine 对象。
  2. 通过调用 candyMachines().update() 更新我们的 Candy Machine。我们首先传入步骤 1 中的 candyMachine,然后定义我们的 guards。每个 guard 都有一个特定的对象键,带有唯一的 GuardSettings。每个 Candy Guard 的设置可在 Metaplex.com 上找到。

    • 开始日期:使用 Metaplex 的 toDateTime 方法传入一个开始日期
    • 铸造限制:为此 guard 传入一个唯一的 id(允许使用 Guard Groups 跟踪不同的限制是必需的)和一个限制数量。
    • SOL 支付:使用 Metaplex 的 sol 方法传入要收集的 SOL 数量以及目标公钥(你的铸造金库)。
  3. 在 Solana Explorer 上记录交易链接。

通过调用 updateCandyMachine() 添加你的 Candy Guards。在应用程序的末尾,添加以下内容:

updateCandyMachine();

然后,在你的终端中运行:

ts-node app

你应该会在终端中看到类似以下内容:

干得好。在继续之前,请删除或注释掉对 updateCandyMachine() 的调用,因为我们不再需要它。

让我们向 Candy Machine 添加一些项目!

向你的 Candy Machine 添加项目

向你的 Candy Machine 添加项目与更新它非常相似。然而,我们不是调用 .update(),而是需要调用 .insertItems()。创建一个新函数 addItems() 并添加以下代码:

async function addItems() {
    const candyMachine = await METAPLEX
        .candyMachines()
        .findByAddress({ address: new PublicKey(CANDY_MACHINE_ID) });
    const items = [];
    for (let i = 0; i < 3; i++ ) { // 添加 3 个 NFT(我们的合集大小)
        items.push({
            name: `Quicknode Demo NFT # ${i+1}`,
            uri: NFT_METADATA
        })
    }
    const { response } = await METAPLEX.candyMachines().insertItems({
        candyMachine,
        items: items,
      },{commitment:'finalized'});

    console.log(`✅ - Items added to Candy Machine: ${CANDY_MACHINE_ID}`);
    console.log(`     https://explorer.solana.com/tx/${response.signature}?cluster=devnet`);
}

我们的函数做了四件事:

  1. 获取我们的 Candy Machine:通过 ID 查找我们的 Candy Machine,并通过调用 .candyMachines().findByAddress() 返回一个 CandyMachine 对象。
  2. 创建一个要添加的项目数组:insertItems() 方法要求我们传入一个 items 数组,其中包含要添加到 Candy Machine 的每个项目的名称uri。由于我们在“初始化 Candy Machine”步骤中将 Candy Machine 的大小设置为 3,我们将使用一个简单的 for 循环添加 3 个项目。如果你正在添加独特的 NFT,请在此处添加你的自定义逻辑。由于 Solana 交易大小受限,我们每次调用只能传递有限数量的项目。“每个交易中可以插入的项目数量将取决于配置行设置中定义的名称长度和 URI 长度属性。我们的名称和 URI 越短,我们就可以在一次交易中容纳更多的项目。”(Metaplex.com)。
  3. 通过调用 candyMachines().insertItems() 将项目插入 Candy Machine:我们首先传入步骤 1 中的 candyMachine,然后传入步骤 2 中定义的 items
  4. 在 Solana Explorer 上记录交易链接。

继续并通过调用 addItems() 添加你的项目。在应用程序的末尾,添加以下内容:

addItems();

然后,在你的终端中运行:

ts-node app

你应该会在终端中看到类似以下内容:

在继续之前,请删除或注释掉对 addItems() 的调用,因为我们不再需要它。

你现在应该有一个已加载且已设置 Guards 的 Candy Machine。让我们来测试一下!

铸造一个 NFT

与我们之前的步骤类似,我们需要获取我们的 Candy Machine 并调用一个新方法 candyMachines().mint()。创建一个新函数 mintNft()

async function mintNft() {
    const candyMachine = await METAPLEX
        .candyMachines()
        .findByAddress({ address: new PublicKey(CANDY_MACHINE_ID) });
    let { nft, response } = await METAPLEX.candyMachines().mint({
        candyMachine,
        collectionUpdateAuthority: WALLET.publicKey,
        },{commitment:'finalized'})

    console.log(`✅ - Minted NFT: ${nft.address.toString()}`);
    console.log(`     https://explorer.solana.com/address/${nft.address.toString()}?cluster=devnet`);
    console.log(`     https://explorer.solana.com/tx/${response.signature}?cluster=devnet`);
}

这段代码应该开始看起来很熟悉了——它做了什么:

  1. 获取我们的 Candy Machine:通过 ID 查找我们的 Candy Machine,并通过调用 .candyMachines().findByAddress() 返回一个 CandyMachine 对象。
  2. 通过调用 candyMachines().mint() 铸造一个 NFT:我们首先传入步骤 1 中的 candyMachine,然后传入我们钱包的公钥作为 collectionUpdateAuthority(必需,因为“此信息不存在于 candyMachine 模型中,并且是底层铸造指令所必需的”来源:Metaplex.com)。
  3. 在 Solana Explorer 上记录铸造和交易的链接。

最后,通过调用 mintNft() 铸造一个 NFT。在应用程序的末尾,添加以下内容:

mintNft();

然后,在你的终端中运行:

ts-node app

你应该会在终端中看到类似以下内容:

干得好!让我们测试一个 Candy Guard。重新运行你的脚本。你应该会看到类似的结果,并向你的钱包铸造第二个 NFT。然后尝试第三次。

第三次尝试应该会给你带来一些问题。为什么?如果你深入研究错误代码,你应该会看到类似以下内容:

  title: CandyGuardProgram > The maximum number of allowed mints was reached,
  problem: The program [CandyGuardProgram] at address [Guard1JwRhJkVH6XZhzoYxeBVQe872VH6QggF4BWmS9g] raised an error of code [6029] that translates to The maximum number of allowed mints was reached.

如果你还记得,我们创建了一个 mintLimit Candy Guard,它限制任何钱包只能铸造 2 个 NFT,所以这个 guard 阻止我们铸造第三个!很酷,是吗?

下一步和总结

你现在有了一些使用 TypeScript 与 Candy Machine 交互的有用脚本!我们很高兴看到你用它构建什么。加入 DiscordTwitter 分享你的项目!

寻找额外的挑战?尝试使用我们刚刚学到的脚本和 Solana dApp Scaffold 创建一个铸造网站!

我们 ❤️ 反馈!

如果你对本指南有任何反馈或疑问,请告诉我们。我们很乐意听取你的意见!

  • 原文链接: quicknode.com/guides/sol...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
QuickNode
QuickNode
江湖只有他的大名,没有他的介绍。