本文详细介绍了如何使用TypeScript在Solana上铸造NFT,涵盖了从项目设置到上传图片和元数据,再到最终铸造NFT的完整步骤。
本指南将深入讲解如何通过一系列技术步骤使用 TypeScript 在 Solana 上铸造 NFT。如果你想更快地完成此任务,而将繁重的工作留给我们,我们建议使用 Crossmint NFT Mint API [主网] 附加组件。通过使用 Crossmint NFT Mint API [主网],你可以通过一个 POST 请求向 Solana 用户和电子邮件地址空投 NFT。使用 NFT Mint API 可以轻松创建集合并铸造 NFT!
尝试 Crossmint NFT Mint API [主网]
使用 Candy Machine 铸造 10,000 个 NFT 非常有趣,但在许多情况下我们可能需要铸造单个 NFT(例如,1 of 1 艺术、音乐等)。Metaplex 是创建 Solana 元数据标准的组织,最近开发了一些方便的 JS SDK,使从终端创建 NFT 变得简单。
在本指南中,你将使用 Metaplex Umi JS 库从终端向 Solana 的 devnet 铸造带有元数据的 NFT。我们将涵盖 NFT 铸造的三个关键步骤:
在构建我们的应用程序之前,让我们谈谈 NFT 和 Solana 的 NFT 架构。那么,NFT到底是什么?非同质化代币实质上是在链上存储的一组唯一数据,和其他任何代币都不相同。简而言之,只有一个。在 Solana 上,我们通过使用 SPL Token Program 并创建一个供给为 1 的代币来实现这一点。此外,NFT 不能被拆分,这意味着你不能拥有 NFT 的三分之一(注:有一些关于分数化的高级 NFT 协议,但通常情况下,NFT 不可分割)。在 Solana 上,我们还使用 SPL Token Program 将 decimals 设置为 0(这意味着它不能被分割)。
尽管创建供给为 1 和 decimals 为 0 的 SPL 代币在技术上是通过其独特的 Mint ID 定义的 NFT,但 SPL token 程序在某些类型和可以存储的数据量方面是有限的。进入 Metaplex。Metaplex 元数据程序为链上和链下元数据设定了标准。通过与 Mint 账户相关联的程序派生地址,Metaplex 允许用户为铸造分配更详细的元数据(例如名称、描述、可变性、卖方费用等)。Metaplex 元数据中一个显著的字段称为 "URI"。这是指向特定链下元数据的地址。由于租赁费用和速度限制,Metaplex 预计某些数据存储在链下(例如图像/图像 URI、NFT 特征/属性)。以下是与这些字段关系可视化的 Metaplex 图示:
来源:*https://docs.metaplex.com/programs/token-metadata/overview\ *
在本指南中,我们将首先将我们的图像上传到 Arweave 并获取其 URI,然后我们将创建链下元数据并上传到 Arweave,最后我们将铸造我们的代币并定义指向链下元数据的链上元数据。
在终端创建一个新的项目目录:
mkdir mint-nft
cd mint-nft
为你的应用程序创建一个文件,app.ts:
echo > app.ts
使用“yes”标志初始化你的项目,以使用默认值创建新包:
yarn init --yes
#或
npm init --yes
创建一个启用 .json 导入的 tsconfig.json 文件:
tsc -init --resolveJsonModule true
最后,创建一个用于上传的文件夹:
mkdir uploads
将图像(.png 或 .jpg)保存到此文件夹中,命名为 image.png。我们将使用这张像素化的美图:
我们需要为本练习添加 Solana Web3 和 SPL Token 库。此外,我们将使用 Metaplex 的 JS SDK 和 MPL Token Metadata 库。在你的终端中输入:
yarn add @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults @metaplex-foundation/mpl-token-metadata @metaplex-foundation/umi-storage-mock
#或
npm install @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults @metaplex-foundation/mpl-token-metadata @metaplex-foundation/umi-storage-mock
你需要创建一个 Solana 文件系统钱包(密钥对将写入 wallet.json 文件)并向其空投一些 SOL。从你的终端,输入:
solana-keygen new --silent --no-bip39-passphrase --outfile wallet.json
这将创建一个新钱包并将其保存到名为 wallet.json 的文件中。然后,你可以使用 QuickNode Faucet 或 Solana Faucet 向该钱包空投一些 SOL。你可以通过输入以下命令获得钱包地址:
solana address -k wallet.json
完成后,你应能够查看你的钱包余额:
solana balance -ud -k wallet.json
如果余额依然为 0,请再次尝试使用水龙头。你将在继续下一个步骤之前需要大约 0.1 Devnet SOL。
打开 app.ts,并在 第 1 行 粘贴以下导入:
import { createNft, mplTokenMetadata } from '@metaplex-foundation/mpl-token-metadata'
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { createGenericFile, createSignerFromKeypair, generateSigner, keypairIdentity, percentAmount, sol } from '@metaplex-foundation/umi';
import { mockStorage } from '@metaplex-foundation/umi-storage-mock';
import * as fs from 'fs';
import secret from './wallet.json';
除了我们在前一步中创建的钱包外,我们还从 Metaplex Umi 库中导入了一些必要的方法和类。此外,由于我们将从系统上传文件,因此需要导入 fs 文件系统库。
要在 Solana 上构建,你需要一个 API 端点来连接到网络。你可以使用公共节点,也可以部署和管理自己的基础设施;然而,如果你希望获得 8 倍的响应速度,你可以将繁重的工作留给我们。
在 app.ts 中的导入语句下声明你的 RPC,并通过初始化新的 Umi 实例与 Solana 进行连接:
const QUICKNODE_RPC = 'https://example.solana-devnet.quiknode.pro/0123456/'; //用你的 QuickNode RPC 端点替换
const umi = createUmi(QUICKNODE_RPC);
你需要在运行脚本之前准备几样东西:
定义你的 Umi 兼容创建者 Signer
配置你的 Umi 实例
定义你的 NFT 元数据
在 Umi 声明下方添加以下声明,以定义你的创建者并配置你的 Umi 实例:
const creatorWallet = umi.eddsa.createKeypairFromSecretKey(new Uint8Array(secret));
const creator = createSignerFromKeypair(umi, creatorWallet);
umi.use(keypairIdentity(creator));
umi.use(mplTokenMetadata());
umi.use(mockStorage());
我们将创建一个 nftDetail
对象,包含我们希望包含在 NFT 中的一些元数据。创建一个新的常量 nftDetail
,并包括以下属性:
const nftDetail = {
name: "QuickNode Pixel",
symbol: "QP",
uri: "IPFS_URL_OF_METADATA",
royalties: 5.5,
description: '面向所有人的像素基础设施!',
imgType: 'image/png',
attributes: [\
{ trait_type: '速度', value: '快速' },\
]
};
请随意在这里使用你自己的值。
在开始之前,我们需要将用于 NFT 的图像上传到一个去中心化存储平台。这是因为我们必须将 NFT 图像的 URI 传递到 NFT 的元数据中。如果你已经有一个拥有 URI 的图像,随意在 main
函数中定义该值并跳过此步骤。
为了上传我们的图像,我们将使用 Umi 上载器。Umi 上载器是一个简单的方法,可将文件上传到 Arweave、IPFS 或其他去中心化存储平台。我们将使用 fs
创建图像缓冲区,然后使用 Umi 上载器进行上传。将以下函数添加到你的 app.ts 文件:
async function uploadImage(): Promise<string> {
try {
const imgDirectory = './uploads';
const imgName = 'image.png'
const filePath = `${imgDirectory}/${imgName}`;
const fileBuffer = fs.readFileSync(filePath);
const image = createGenericFile(
fileBuffer,
imgName,
{
uniqueName: nftDetail.name,
contentType: nftDetail.imgType
}
);
const [imgUri] = await umi.uploader.upload([image]);
console.log('已上传图像:', imgUri);
return imgUri;
} catch (e) {
throw e;
}
}
Umi 上载器接口
如果你密切关注我们之前的依赖安装和导入,你可能会注意到我们正在使用一个名为 @metaplex-foundation/umi-storage-mock
的包。正如其名,这是一种模拟存储系统,允许我们在不实际上传文件到去中心化存储平台的情况下测试我们的代码。这对于测试和调试非常有用(使用也不花费任何钱!)。Umi 的一个伟大方面是它为存储(以及其他常见操作)提供了原始的通用函数,这些可以轻松替换为真实的存储系统,例如 Arweave 或 IPFS。这是通过 UploaderInterface
实现的。这意味着你可以通过简单的导入和配置更改,将模拟存储替换为不同的插件。以下是当前替代 UploaderInterface 选项的 列表。你需要做的就是导入相关包,并将 umi.use(mockStorage())
这一行更改为 umi.use(newStoragePlugin())
。
非常酷!
元数据或多或少就是使你的 NFT 特别的东西。它包括图像、任何定义特征、将其分配给集合等。我们将使用与上一步上传图像类似的方法,但有一种特殊的方法来处理 .json 文件。将以下函数添加到你的 app.ts 文件:
async function uploadMetadata(imageUri: string): Promise<string> {
try {
const metadata = {
name: nftDetail.name,
description: nftDetail.description,
image: imageUri,
attributes: nftDetail.attributes,
properties: {
files: [\
{\
type: nftDetail.imgType,\
uri: imageUri,\
},\
]
}
};
const metadataUri = await umi.uploader.uploadJson(metadata);
console.log('已上传元数据:', metadataUri);
return metadataUri;
} catch (e) {
throw e;
}
}
在这里,我们创建了一个 JSON 对象,包含我们希望包含在 NFT 中的元数据。然后我们使用 Umi 上载器的 uploadJson
方法上传这个 JSON 对象。元数据对象包括名称、描述、图像 URI、属性和 NFT 的属性。你可以稍微调整一下,但请确保符合 Metaplex 元数据标准。
与我们之前的函数一样,Metaplex API 简化了这个过程,让我们能够通过一个方法 createNft 铸造 NFT。与上一步中的元数据不同,在最后这一步中,我们必须传入一些将直接存储在 Solana 链上的元数据。
在你的 uploadMetadata() 函数之后和 main() 之前,创建一个新的异步函数 mintNft():
async function mintNft(metadataUri: string) {
try {
const mint = generateSigner(umi);
await createNft(umi, {
mint,
name: nftDetail.name,
symbol: nftDetail.symbol,
uri: metadataUri,
sellerFeeBasisPoints: percentAmount(nftDetail.royalties),
creators: [{ address: creator.publicKey, verified: true, share: 100 }],
}).sendAndConfirm(umi)
console.log(`创建的 NFT: ${mint.publicKey.toString()}`)
} catch (e) {
throw e;
}
}
此函数将在链上铸造一个代币,链接到我们的元数据,使用 Metaplex 元数据程序。
创建一个异步函数 main,用于执行我们代码的所有步骤:
async function main() {
const imageUri = await uploadImage();
const metadataUri = await uploadMetadata(imageUri);
await mintNft(metadataUri);
}
main();
如你所见,我们需要定义三个函数:uploadImage、uploadMetadata 和 mintNft。我们将在 main 函数中调用这些函数。让我们从 uploadImage 开始。
现在,你只需运行你的代码!
你已经准备好了!当你准备好时,在终端中输入:
ts-node app
是的!你看到这样的输出了吗?
ts-node app
已上传图像: https://mockstorage.example.com/QuickNode Pixel
已上传元数据: https://mockstorage.example.com/Km5iewgZoHUE1dIQJZx7
创建的 NFT: 2dgA2xB4MebkQTMZeucoN1crDrPcLPaBryWChaUBcU6x
做得很好。
你现在拥有一个方便且可重用的脚本,可以直接从终端铸造 NFT!这很方便,对吧?想继续构建吗?以下是一些可以扩展你刚学到的内容的想法:
- 原文链接: quicknode.com/guides/sol...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!