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

QuickNode 发布于 2025-01-30 阅读 2279

本文介绍了如何使用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 条评论