如何使用 Metaplex Core Candy Machine 启动 NFT 收藏品

  • QuickNode
  • 发布于 2025-01-30 12:22
  • 阅读 17

本文介绍了如何使用Metaplex Core标准创建和铸造NFT,通过Candy Machine工具的详细步骤,包括创建项目、上传NFT图像到IPFS、创建Candy Machine、铸造NFT等。读者需要具备一定的Metaplex Core和Candy Machine基础知识,文中提供了实际的代码示例和相关库的使用说明。

概述

Metaplex 最近推出了一个用于他们新 Metaplex Core 标准的 Candy Machine 工具。Candy Machine 是一个让创作者能够公平透明地出售/分发大量 NFTs 的工具,而 Metaplex Core 是一个低成本/灵活的标准,用于在 Solana 上铸造 NFTs。

本指南将教你如何创建一个 Core Candy Machine 并使用 Umi JavaScript 库铸造 NFTs。

让我们开始吧!

你将做什么

编写一个脚本来:

  • 将 NFT 图像和元数据上传到 IPFS
  • 创建一个 Core NFT 收藏
  • 部署一个 Core Candy Machine
  • 使用 Candy Machine 铸造 NFTs
  • 删除 Candy Machine 并回收租金

你需要什么

本指南假设你对 Metaplex Core 标准和 Candy Machine 有基本了解。如果你对这些概念不熟悉,请在开始之前查看以下指南:

你需要以下工具和依赖项来完成本指南:

本指南中使用的依赖项

依赖项 版本
@metaplex-foundation/umi ^0.9.1
@metaplex-foundation/umi-bundle-defaults ^0.9.1
@metaplex-foundation/mpl-core-candy-machine ^0.2.0
solana cli 1.18.1

让我们开始吧!

什么是 Core Candy Machine?

Core Candy Machine ("CCM") 是一个新工具,将 Metaplex 的 Candy Machine 和 Candy Guards 的强大功能带入 Metaplex Core 标准。它使创作者能够使用 Candy Guards 规定铸造规则,公平透明地将 NFTs 分发给他们的受众。Candy Machines 是部署到 Solana 区块链上的临时帐户,使用户能够铸造 NFTs。

设置你的项目

创建一个新的项目目录。在终端中输入:

mkdir core-cm-example
cd core-cm-example

使用 npm 初始化一个新项目:

npm init -y

在你的项目目录中创建一个新的 TypeScript 文件:

echo > app.ts

下载必要的程序

今天我们将使用本地验证器运行测试。因为 Candy Machine 和 Candy Guard 程序没有包含在你本地的验证器中,所以我们需要从网络上下载它们,以便在启动本地验证器时进行初始化。

solana program dump -um CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d core.so
solana program dump -um CMACYFENjoBMHzapRXyo1JZkVS6EtaDDzkjMrmQLvr4J candy_machine_core.so
solana program dump -um CMAGAKJ67e9hRZgfC5SFTbZH8MgEmtqazKXjmkaJjWTJ candy_guard.so

这些命令将程序可执行数据写入项目目录中的文件。我们将在准备好运行脚本时使用这些文件。

安装依赖项

接下来,安装项目所需的依赖项:

npm install @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults @metaplex-foundation/mpl-core-candy-machine

app.ts 文件中添加以下导入:

import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import {
    mplCandyMachine as mplCoreCandyMachine,
    create,
    addConfigLines,
    fetchCandyMachine,
    deleteCandyMachine,
    mintV1,
} from '@metaplex-foundation/mpl-core-candy-machine'
import {
    Umi,
    PublicKey,
    generateSigner,
    transactionBuilder,
    keypairIdentity,
    some,
    sol,
    dateTime,
    TransactionBuilderSendAndConfirmOptions,
} from '@metaplex-foundation/umi'
import { createCollectionV1 } from '@metaplex-foundation/mpl-core'
import { setComputeUnitLimit } from '@metaplex-foundation/mpl-toolbox'

我们将使用这些导入来创建和部署我们的 Core Candy Machine——我们会在后面的过程中详细讨论这些函数。

定义关键变量

在开始构建之前,让我们使用本地 Solana 集群和将用于签名交易的密钥对来定义我们的 umi 实例。

const umi = createUmi('http://127.0.0.1:8899').use(mplCoreCandyMachine())

const keypair = generateSigner(umi)
const collectionMint = generateSigner(umi)
const treasury = generateSigner(umi)
const candyMachine = generateSigner(umi)

umi.use(keypairIdentity(keypair))

const options: TransactionBuilderSendAndConfirmOptions = {
    send: { skipPreflight: true },
    confirm: { commitment: 'processed' },
}

async function main() {
    console.log(`Testing Candy Machine Core...`)
    console.log(`重要账户信息:`)
    console.table({
        keypair: keypair.publicKey.toString(),
        collectionMint: collectionMint.publicKey.toString(),
        treasury: treasury.publicKey.toString(),
        candyMachine: candyMachine.publicKey.toString(),
    })

    // 1. Airdrop 100 SOL 给密钥对

    // 2. 创建一个集合

    // 3. 创建一个 Candy Machine

    // 4. 向 Candy Machine 添加项目

    // 5. 验证 Candy Machine 配置

    // 6. 铸造 NFTs

    // 7. 验证 Candy Machine 配置

    // 8. 删除 Candy Machine
}
main().catch(console.error)

以下是我们添加内容的摘要:

  • 我们利用 createUmi 创建了 Umi 库的实例,并传入我们本地 Solana 集群的 URL。我们还利用 mplCoreCandyMachine 函数将 Candy Machine 程序添加到我们的 Umi 实例中。
  • 我们使用 generateSigner 为我们的 keypair(我们的支付者/主要签署者)、collectionMinttreasurycandyMachine 创建了密钥对。
  • 我们将 keypair 设置为我们 Umi 实例的主要签署者。
  • 我们定义了一个 options 对象,用于发送和确认交易。在我们的测试环境中,我们跳过了预检查,并将承诺级别设置为 processed——这将确保我们的交易迅速处理。你可能希望在生产环境中更改此设置。
  • 除了我们的常量外,我们还定义了一个名为 main 的函数来运行我们的脚本。我们将在逐步过程中填充 main 函数的步骤。

创建辅助函数

我们将创建一个辅助函数,用于获取我们的集合并验证链上数据是否符合我们的预期。在 main 下添加以下内容:

interface ExpectedCandyMachineState {
    itemsLoaded: number
    itemsRedeemed: number
    authority: PublicKey
    collection: PublicKey
}

async function checkCandyMachine(
    umi: Umi,
    candyMachine: PublicKey,
    expectedCandyMachineState: ExpectedCandyMachineState,
    step?: number
) {
    try {
        const loadedCandyMachine = await fetchCandyMachine(
            umi,
            candyMachine,
            options.confirm
        )
        const { itemsLoaded, itemsRedeemed, authority, collection } =
            expectedCandyMachineState
        if (Number(loadedCandyMachine.itemsRedeemed) !== itemsRedeemed) {
            throw new Error(
                'Candy Machine 中可用项目数量不正确。'
            )
        }
        if (loadedCandyMachine.itemsLoaded !== itemsLoaded) {
            throw new Error('Candy Machine 中加载的项目数量不正确。')
        }
        if (loadedCandyMachine.authority.toString() !== authority.toString()) {
            throw new Error('Candy Machine 中的权限不正确。')
        }
        if (
            loadedCandyMachine.collectionMint.toString() !== collection.toString()
        ) {
            throw new Error('Candy Machine 中的集合不正确。')
        }
        step &&
            console.log(`${step}. ✅ - Candy Machine 配置正确。`)
    } catch (error) {
        if (error instanceof Error) {
            step &&
                console.log(
                    `${step}. ❌ - Candy Machine 配置不正确: ${error.message}`
                )
        } else {
            step && console.log(`${step}. ❌ - 获取 Candy Machine 时出错。`)
        }
    }
}

在这里,我们创建了一个 TypeScript 接口,用于定义我们 Candy Machine 的预期状态。我们的辅助函数 checkCandyMachine 将接受一个 umi 实例、candyMachine 公钥和 Candy Machine 的预期状态。该函数使用 fetchCandyMachine 函数获取 Candy Machine 的当前状态并与预期状态进行比较。如果状态不匹配,函数将抛出错误。

第一步 - 空投 SOL

由于我们将在本地主机上工作,所以每次运行脚本时,我们将需要对密钥对进行 100 SOL 的空投。在 main 函数中添加以下代码:

// 1. Airdrop 100 SOL 给密钥对
try {
    await umi.rpc.airdrop(keypair.publicKey, sol(100), options.confirm)
    console.log(
        `1. ✅ - 已空投 100 SOL 到 ${keypair.publicKey.toString()}`
    )
} catch (error) {
    console.log('1. ❌ - 向钱包空投 SOL 时出错。')
}

我们使用 umi.rpc.airdrop 函数向密钥对发送 100 SOL。

第二步 - 创建一个集合

接下来,我们将为要铸造的 NFTs 创建一个集合。在 main 函数中添加以下代码:

// 2. 创建一个集合
try {
    await createCollectionV1(umi, {
        collection: collectionMint,
        name: '我的集合',
        uri: 'https://example.com/my-collection.json',
    }).sendAndConfirm(umi, options)
    console.log(
        `2. ✅ - 创建集合: ${collectionMint.publicKey.toString()}`
    )
} catch (error) {
    console.log('2. ❌ - 创建集合时出错。')
}

我们使用 createCollectionV1 函数创建一个新集合。我们传入 collectionMint 密钥对、集合的名称和将存储集合元数据的 URI。确保用你自己的元数据更新 URI,并确保它符合 Metaplex Non-Fungible Token Metadata 标准

第三步 - 创建一个 Candy Machine

现在我们有了一个集合,可以使用 mpl-core-candy-machine 包中的 create 函数创建一个新的 Candy Machine。在 main 函数中添加以下代码:

// 3. 创建一个 Candy Machine
try {
    const createIx = await create(umi, {
        candyMachine,
        collection: collectionMint.publicKey,
        collectionUpdateAuthority: umi.identity,
        itemsAvailable: 3,
        authority: umi.identity.publicKey,
        isMutable: false,
        configLineSettings: some({
            prefixName: 'Quick NFT #',
            nameLength: 11,
            prefixUri: 'https://example.com/metadata/',
            uriLength: 29,
            isSequential: false,
        }),
        guards: {
            botTax: some({ lamports: sol(0.001), lastInstruction: true }),
            solPayment: some({ lamports: sol(1.5), destination: treasury.publicKey }),
            startDate: some({ date: dateTime('2023-04-04T16:00:00Z') }),
            // 其他所有 guards 被禁用...
        },
    })
    await createIx.sendAndConfirm(umi, options)
    console.log(
        `3. ✅ - 创建 Candy Machine: ${candyMachine.publicKey.toString()}`
    )
} catch (error) {
    console.log('3. ❌ - 创建 Candy Machine 时出错。')
}

create 函数接收我们的 umi 实例和一个对象,具有以下属性:

  • candyMachine:Candy Machine 账户的公钥
  • collection:我们在步骤 2 中创建的集合的公钥
  • collectionUpdateAuthority:集合更新权限的公钥
  • itemsAvailable:将在 Candy Machine 中可用的 NFTs 数量
  • authority:将控制 Candy Machine 的权限的公钥
  • isMutable:布尔值,决定从 Candy Machine 中铸造的 NFTs 是否可以变更
  • configLineSettings:一个定义将铸造的 NFTs 配置的对象。通过使用名称和 URI 的前缀和长度,这可以帮助减少 NFT 元数据的大小。例如,如果我们将 prefixName 设置为 'Quick NFT #' 且 nameLength 设置为 11,NFT 的名称将为 'Quick NFT #1'、'Quick NFT #2' 等,而无需在 Candy Machine 中为每个 NFT 存储相同的前缀。
  • guards:定义从 Candy Machine 铸造 NFTs 的规则的对象。在这个例子中,我们设置了 0.001 SOL 的机器人税、1.5 SOL 的支付到国库,起始日期是 2023 年 4 月 4 日。你可以根据需要添加其他 guards。

有关配置设置和 candy guards 的更多信息,请查看我们关于 Candy Machine v. 3 的指南或 Metaplex Core Candy Machine 文档

第四步 - 向 Candy Machine 添加项目

现在我们的 Candy Machine 已经初始化,我们需要向其中添加项目。由于我们使用了 configLineSettings 对象来定义将要铸造的 NFTs 的配置,我们可以使用 addConfigLines 函数,以简化的名称和 URI 向 Candy Machine 添加项目(例如,用 1 替代 Quick NFT #1,用 1.json 替代 https://example.com/metadata/1.json)。在 main 函数中添加以下代码:

// 4. 向 Candy Machine 添加项目
try {
    await addConfigLines(umi, {
        candyMachine: candyMachine.publicKey,
        index: 0,
        configLines: [\
            { name: '1', uri: '1.json' },\
            { name: '2', uri: '2.json' },\
            { name: '3', uri: '3.json' },\
        ],
    }).sendAndConfirm(umi, options)
    console.log(
        `4. ✅ - 已向 Candy Machine 添加项目: ${candyMachine.publicKey.toString()}`
    )
} catch (error) {
    console.log('4. ❌ - 向 Candy Machine 添加项目时出错。')
}

addConfigLines 函数接收我们的 umi 实例和一个对象,具有以下属性:

  • candyMachine:Candy Machine 账户的公钥
  • index:要添加的第一个项目的索引(如果你多次运行该脚本,可能需要调整此索引以避免覆盖现有项目)
  • configLines:一个定义要添加到 Candy Machine 中的每个项目的名称和 URI 的对象数组。

第五步 - 验证 Candy Machine 配置

在铸造 NFTs 之前,让我们使用我们的辅助函数 checkCandyMachine 验证 Candy Machine 配置是否符合我们的预期。在 main 函数中添加以下代码:

// 5. 验证 Candy Machine 配置
await checkCandyMachine(
    umi,
    candyMachine.publicKey,
    {
        itemsLoaded: 3,
        authority: umi.identity.publicKey,
        collection: collectionMint.publicKey,
        itemsRedeemed: 0,
    },
    5
)

我们这时期望我们的 Candy Machine 应该有三个项目已加载,且没有已赎回。如果配置不匹配,checkCandyMachine 函数将抛出一个错误。

第六步 - 铸造 NFTs

让我们从 Candy Machine 中铸造所有 NFTs。我们可以编写一个简单的循环,为每个项目调用 mintV1 函数。在 main 函数中添加以下代码:

// 6. 铸造 NFTs
try {
    const numMints = 3
    let minted = 0
    for (let i = 0; i < numMints; i++) {
        await transactionBuilder()
            .add(setComputeUnitLimit(umi, { units: 800_000 }))
            .add(
                mintV1(umi, {
                    candyMachine: candyMachine.publicKey,
                    asset: generateSigner(umi),
                    collection: collectionMint.publicKey,
                    mintArgs: {
                        solPayment: some({ destination: treasury.publicKey }),
                    },
                })
            )
            .sendAndConfirm(umi, options)
        minted++
    }
    console.log(`6. ✅ - 已铸造 ${minted} 个 NFTs。`)
} catch (error) {
    console.log('6. ❌ - 铸造 NFTs 时出错。')
}

mintV1 函数要求我们为新的 NFT 生成一个地址(我们在这里使用 generateSigner 函数),集合公钥,以及铸造参数。在这个例子中,我们只需要传入 solPayment guard,以将 1.5 SOL 发送到国库,仅此而已(因为并不是所有的 guards 都需要参数)。可以查看 Metaplex Core Candy Machine 文档 以获取你计划使用的每个参数的更多信息。

第七步 - 验证 Candy Machine 配置

现在我们已经铸造了 NFTs,我们应该期望我们的 Candy Machine 配置发生了变化。让我们使用我们的 checkCandyMachine 函数验证配置是否符合我们的预期。在 main 函数中添加以下代码:

// 7. 验证 Candy Machine 配置
await checkCandyMachine(
    umi,
    candyMachine.publicKey,
    {
        itemsLoaded: 3,
        authority: umi.identity.publicKey,
        collection: collectionMint.publicKey,
        itemsRedeemed: 3,
    },
    7
)

我们期望我们的 Candy Machine 仍然有三个项目已加载,但现在它们都应该被赎回。如果配置不匹配,checkCandyMachine 函数将抛出错误。

第八步 - 删除 Candy Machine

最后,随着我们的铸造完成,我们将删除 Candy Machine 并回收租金。在 main 函数中添加以下代码:

// 8. 删除 Candy Machine
try {
    await deleteCandyMachine(umi, {
        candyMachine: candyMachine.publicKey,
    }).sendAndConfirm(umi, options)
    console.log(
        `8. ✅ - 已删除 Candy Machine: ${candyMachine.publicKey.toString()}`
    )
} catch (error) {
    console.log('8. ❌ - 删除 Candy Machine 时出错。')
}

deleteCandyMachine 函数接收我们的 umi 实例和一个包含 Candy Machine 账户公钥的对象。该函数将删除 Candy Machine 并回收用于创建它的租金。在这一步之后,Candy Machine 账户将不再存在于链上,Candy Machine 将不可使用。如果我们在删除 Candy Machine 后运行 checkCandyMachine 函数,将抛出错误。

干得好,你的脚本现在完成了!让我们启动本地验证器并运行脚本。

运行你的脚本

要运行脚本,请使用我们之前下载的程序启动本地验证器。确保从存放这些文件的目录运行(或提供文件的完整路径):

solana-test-validator -r \
  --bpf-program CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d core.so \
  --bpf-program CMACYFENjoBMHzapRXyo1JZkVS6EtaDDzkjMrmQLvr4J candy_machine_core.so \
  --bpf-program CMAGAKJ67e9hRZgfC5SFTbZH8MgEmtqazKXjmkaJjWTJ candy_guard.so

你的验证器应该加载程序并启动:

Solana 测试验证器

你应该能够使用 Solana Explorer 的自定义集群视图查看程序链上状态,链接 这里

然后,运行你的 Candy Machine 脚本。在终端中运行:

ts-node app.ts

你的脚本应该成功运行并输出类似以下内容:

脚本输出

干得好!

甜蜜的成功

你已经成功创建并铸造了 NFTs,使用了 Metaplex Core Candy Machine。你现在拥有构建和部署利用 Metaplex Core 标准独特灵活性和低成本的 Candy Machine 的工具。

如果你有任何问题或想要分享的想法,请通过 DiscordTwitter 与我们联系!

我们 ❤️ 反馈!

让我们知道 如果你有任何反馈或新主题的请求。我们非常乐意听取你的建议。

资源

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

0 条评论

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