本文介绍了如何使用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。
让我们开始吧!
编写一个脚本来:
本指南假设你对 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 ("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
(我们的支付者/主要签署者)、collectionMint
、treasury
和 candyMachine
创建了密钥对。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 的当前状态并与预期状态进行比较。如果状态不匹配,函数将抛出错误。
由于我们将在本地主机上工作,所以每次运行脚本时,我们将需要对密钥对进行 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 标准。
现在我们有了一个集合,可以使用 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 已经初始化,我们需要向其中添加项目。由于我们使用了 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 的对象数组。在铸造 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
函数将抛出一个错误。
让我们从 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 文档 以获取你计划使用的每个参数的更多信息。
现在我们已经铸造了 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 并回收租金。在 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 Explorer 的自定义集群视图查看程序链上状态,链接 这里。
然后,运行你的 Candy Machine 脚本。在终端中运行:
ts-node app.ts
你的脚本应该成功运行并输出类似以下内容:
干得好!
你已经成功创建并铸造了 NFTs,使用了 Metaplex Core Candy Machine。你现在拥有构建和部署利用 Metaplex Core 标准独特灵活性和低成本的 Candy Machine 的工具。
如果你有任何问题或想要分享的想法,请通过 Discord 或 Twitter 与我们联系!
让我们知道 如果你有任何反馈或新主题的请求。我们非常乐意听取你的建议。
- 原文链接: quicknode.com/guides/sol...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!