如何在 Solana 上创建 NFT
Last updated June 18, 2024
这是关于如何使用 Metaplex Token Metadata 协议在 Solana 区块链上创建 NFT 的入门指南。
前提条件
- 您选择的代码编辑器(推荐 Visual Studio Code)
- Node 18.x.x 或更高版本。
初始设置
本指南将介绍基于单文件脚本使用 Javascript 创建 NFT。您可能需要修改和移动函数以适应您的需求。
初始化
首先使用您选择的包管理器(npm、yarn、pnpm、bun)初始化一个新项目(可选),并在提示时填写所需的详细信息。
npm init
所需包
安装本指南所需的包。
1import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
2import { generateSigner, percentAmount } from '@metaplex-foundation/umi';
3import {
4 mplTokenMetadata,
5 createNft,
6 fetchDigitalAsset,
7} from '@metaplex-foundation/mpl-token-metadata';
8
9// Create Umi instance with the Token Metadata plugin
10const umi = createUmi('https://api.devnet.solana.com')
11 .use(mplTokenMetadata());
12
13// Connect your wallet (keypair or wallet adapter)
14// For keypair: umi.use(keypairIdentity(keypair))
15// For wallet adapter: umi.use(walletAdapterIdentity(wallet))
16
17// Generate a new mint keypair
18const mint = generateSigner(umi);
19
20// Create an NFT
21await createNft(umi, {
22 mint,
23 name: 'My NFT',
24 uri: 'https://example.com/my-nft.json',
25 sellerFeeBasisPoints: percentAmount(5.5),
26}).sendAndConfirm(umi);
27
28// Fetch the NFT data
29const asset = await fetchDigitalAsset(umi, mint.publicKey);
30
31console.log('NFT created successfully!');
32console.log('Mint address:', mint.publicKey);
33console.log('Name:', asset.metadata.name);
34console.log('URI:', asset.metadata.uri);
1import {
2 appendTransactionMessageInstructions,
3 createSolanaRpc,
4 createSolanaRpcSubscriptions,
5 createTransactionMessage,
6 generateKeyPairSigner,
7 getSignatureFromTransaction,
8 type Instruction,
9 type TransactionSigner,
10 pipe,
11 sendAndConfirmTransactionFactory,
12 setTransactionMessageFeePayer,
13 setTransactionMessageLifetimeUsingBlockhash,
14 signTransactionMessageWithSigners,
15} from '@solana/kit';
16import {
17 createNft,
18 fetchDigitalAsset,
19} from '@metaplex-foundation/mpl-token-metadata-kit';
20
21// Create RPC connection
22const rpc = createSolanaRpc('https://api.devnet.solana.com');
23const rpcSubscriptions = createSolanaRpcSubscriptions('wss://api.devnet.solana.com');
24
25// Generate keypairs (or load from wallet)
26const authority = await generateKeyPairSigner();
27const mint = await generateKeyPairSigner();
28
29// Helper function to send and confirm transactions
30// Works with any signer type - signers are automatically extracted from instruction accounts
31async function sendAndConfirm(options: {
32 instructions: Instruction[];
33 payer: TransactionSigner;
34}) {
35 const { instructions, payer } = options;
36 const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
37
38 const transactionMessage = pipe(
39 createTransactionMessage({ version: 0 }),
40 (tx) => setTransactionMessageFeePayer(payer.address, tx),
41 (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
42 (tx) => appendTransactionMessageInstructions(instructions, tx),
43 );
44
45 // Sign with all signers attached to instruction accounts
46 const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
47
48 const sendAndConfirmTx = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
49 await sendAndConfirmTx(signedTransaction, { commitment: 'confirmed' });
50
51 return getSignatureFromTransaction(signedTransaction);
52}
53
54// Create and mint an NFT using the helper function
55const [createIx, mintIx] = await createNft({
56 mint,
57 authority,
58 payer: authority,
59 name: 'My NFT',
60 uri: 'https://example.com/my-nft.json',
61 sellerFeeBasisPoints: 550, // 5.5%
62 tokenOwner: authority.address,
63});
64
65// Send transaction
66const sx = await sendAndConfirm({
67 instructions: [createIx, mintIx],
68 payer: authority,
69});
70
71// Fetch the NFT data
72const asset = await fetchDigitalAsset(rpc, mint.address);
73
74console.log('NFT created successfully!');
75console.log('Mint address:', mint.address);
76console.log('Signature:', sx);
77console.log('Name:', asset.metadata.name);
78console.log('URI:', asset.metadata.uri);
设置 SDK
1import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
2import { generateSigner, percentAmount } from '@metaplex-foundation/umi';
3import {
4 mplTokenMetadata,
5 createNft,
6 fetchDigitalAsset,
7} from '@metaplex-foundation/mpl-token-metadata';
8
9// Create Umi instance with the Token Metadata plugin
10const umi = createUmi('https://api.devnet.solana.com')
11 .use(mplTokenMetadata());
12
13// Connect your wallet (keypair or wallet adapter)
14// For keypair: umi.use(keypairIdentity(keypair))
15// For wallet adapter: umi.use(walletAdapterIdentity(wallet))
16
17// Generate a new mint keypair
18const mint = generateSigner(umi);
19
20// Create an NFT
21await createNft(umi, {
22 mint,
23 name: 'My NFT',
24 uri: 'https://example.com/my-nft.json',
25 sellerFeeBasisPoints: percentAmount(5.5),
26}).sendAndConfirm(umi);
27
28// Fetch the NFT data
29const asset = await fetchDigitalAsset(umi, mint.publicKey);
30
31console.log('NFT created successfully!');
32console.log('Mint address:', mint.publicKey);
33console.log('Name:', asset.metadata.name);
34console.log('URI:', asset.metadata.uri);
1import {
2 appendTransactionMessageInstructions,
3 createSolanaRpc,
4 createSolanaRpcSubscriptions,
5 createTransactionMessage,
6 generateKeyPairSigner,
7 getSignatureFromTransaction,
8 type Instruction,
9 type TransactionSigner,
10 pipe,
11 sendAndConfirmTransactionFactory,
12 setTransactionMessageFeePayer,
13 setTransactionMessageLifetimeUsingBlockhash,
14 signTransactionMessageWithSigners,
15} from '@solana/kit';
16import {
17 createNft,
18 fetchDigitalAsset,
19} from '@metaplex-foundation/mpl-token-metadata-kit';
20
21// Create RPC connection
22const rpc = createSolanaRpc('https://api.devnet.solana.com');
23const rpcSubscriptions = createSolanaRpcSubscriptions('wss://api.devnet.solana.com');
24
25// Generate keypairs (or load from wallet)
26const authority = await generateKeyPairSigner();
27const mint = await generateKeyPairSigner();
28
29// Helper function to send and confirm transactions
30// Works with any signer type - signers are automatically extracted from instruction accounts
31async function sendAndConfirm(options: {
32 instructions: Instruction[];
33 payer: TransactionSigner;
34}) {
35 const { instructions, payer } = options;
36 const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
37
38 const transactionMessage = pipe(
39 createTransactionMessage({ version: 0 }),
40 (tx) => setTransactionMessageFeePayer(payer.address, tx),
41 (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
42 (tx) => appendTransactionMessageInstructions(instructions, tx),
43 );
44
45 // Sign with all signers attached to instruction accounts
46 const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
47
48 const sendAndConfirmTx = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
49 await sendAndConfirmTx(signedTransaction, { commitment: 'confirmed' });
50
51 return getSignatureFromTransaction(signedTransaction);
52}
53
54// Create and mint an NFT using the helper function
55const [createIx, mintIx] = await createNft({
56 mint,
57 authority,
58 payer: authority,
59 name: 'My NFT',
60 uri: 'https://example.com/my-nft.json',
61 sellerFeeBasisPoints: 550, // 5.5%
62 tokenOwner: authority.address,
63});
64
65// Send transaction
66const sx = await sendAndConfirm({
67 instructions: [createIx, mintIx],
68 payer: authority,
69});
70
71// Fetch the NFT data
72const asset = await fetchDigitalAsset(rpc, mint.address);
73
74console.log('NFT created successfully!');
75console.log('Mint address:', mint.address);
76console.log('Signature:', sx);
77console.log('Name:', asset.metadata.name);
78console.log('URI:', asset.metadata.uri);
创建 NFT
上传图像
首先需要做的是上传一个代表 NFT 并使其可识别的图像。这可以是 jpeg、png 或 gif 格式。
Umi 附带可下载的存储插件,允许您上传到 Arweave、NftStorage、AWS 和 ShdwDrive 等存储解决方案。在本指南开始时,我们安装了 irysUploader() 插件,它将内容存储在 Arweave 区块链上。
本地脚本/Node.js
此示例使用本地脚本/node.js 方法,使用 Irys 上传到 Arweave。如果您希望将文件上传到其他存储提供商或从浏览器上传,则需要采用不同的方法。在浏览器场景中,导入和使用 fs 将不起作用。
Error: Could not load example "token-metadata/upload-assets"
Make sure the file exists at: src/examples/token-metadata/upload-assets/index.js
Cannot find module './token-metadata/upload-assets/index.js'
上传元数据
一旦我们有了有效且可用的图像 URI,就可以开始处理 NFT 的元数据了。
链下元数据的标准如下:
{
"name": "My NFT",
"description": "This is an NFT on Solana",
"image": "https://arweave.net/my-image",
"external_url": "https://example.com/my-nft.json",
"attributes": [
{
"trait_type": "trait1",
"value": "value1"
},
{
"trait_type": "trait2",
"value": "value2"
}
],
"properties": {
"files": [
{
"uri": "https://arweave.net/my-image",
"type": "image/png"
}
],
"category": "image"
}
}
字段说明:
name
代币的名称。
symbol
代币的缩写。Solana 的缩写是 SOL。
description
代币的描述。
image
这将设置为我们之前上传的 imageUri(或图像的任何在线位置)。
NFT vs pNFT
Token Metadata 程序可以铸造 2 种 NFT,普通 NFT 和 pNFT(可编程非同质化资产)。 这两种类型 NFT 的主要区别是一种强制执行版税(pNFT),另一种不执行(NFT)。
NFT
- 无版税强制执行
- 初始设置更简单,将来更容易使用
pNFT
- 在未来开发方面需要处理更多账户
- 版税强制执行
- 可编程 - 我们有规则集可以阻止程序进行转移
铸造 NFT
从这里您可以选择要使用的 NFT 铸造指令类型,NFT 或 pNFT。
NFT
1import { percentAmount, generateSigner } from '@metaplex-foundation/umi';
2import { createNft } from '@metaplex-foundation/mpl-token-metadata';
3
4// Assuming umi is set up with mplTokenMetadata plugin
5// See getting-started for full setup
6
7const mint = generateSigner(umi);
8
9// Create and mint an NFT in one step
10await createNft(umi, {
11 mint,
12 name: 'My NFT',
13 uri: 'https://example.com/my-nft.json',
14 sellerFeeBasisPoints: percentAmount(5.5),
15 // Optional: add to collection (must verify separately)
16 // collection: some({ key: collectionMint.publicKey, verified: false }),
17}).sendAndConfirm(umi);
18
19console.log('NFT created:', mint.publicKey);
1import { generateKeyPairSigner } from '@solana/kit';
2import { createNft } from '@metaplex-foundation/mpl-token-metadata-kit';
3
4// Assuming rpc, rpcSubscriptions, and sendAndConfirmInstructions are set up
5// See getting-started for full setup
6
7const mint = await generateKeyPairSigner();
8const authority = await generateKeyPairSigner(); // Your wallet
9
10// Create and mint an NFT in one step
11const [createIx, mintIx] = await createNft({
12 mint,
13 authority,
14 payer: authority,
15 name: 'My NFT',
16 uri: 'https://example.com/my-nft.json',
17 sellerFeeBasisPoints: 550, // 5.5%
18 tokenOwner: authority.address,
19 // Optional: add to collection (must verify separately)
20 // collection: { key: collectionMint.address, verified: false },
21});
22
23// Send both instructions in one transaction
24await sendAndConfirm({
25 instructions: [createIx, mintIx],
26 payer: authority,
27});
28
29console.log('NFT created:', mint.address);
pNFT
1import { percentAmount, generateSigner } from '@metaplex-foundation/umi';
2import { createProgrammableNft } from '@metaplex-foundation/mpl-token-metadata';
3
4// Assuming umi is set up with mplTokenMetadata plugin
5
6const mint = generateSigner(umi);
7
8// Create and mint a Programmable NFT in one step
9await createProgrammableNft(umi, {
10 mint,
11 name: 'My Programmable NFT',
12 uri: 'https://example.com/my-programmable-nft.json',
13 sellerFeeBasisPoints: percentAmount(5.5),
14 // Optional: add to collection (must verify separately)
15 // collection: some({ key: collectionMint.publicKey, verified: false }),
16}).sendAndConfirm(umi);
17
18console.log('Programmable NFT created:', mint.publicKey);
1import { generateKeyPairSigner } from '@solana/kit';
2import { createProgrammableNft } from '@metaplex-foundation/mpl-token-metadata-kit';
3
4// Assuming rpc, rpcSubscriptions, and sendAndConfirmInstructions are set up
5
6const mint = await generateKeyPairSigner();
7const authority = await generateKeyPairSigner(); // Your wallet
8
9// Create and mint a Programmable NFT in one step
10const [createIx, mintIx] = await createProgrammableNft({
11 mint,
12 authority,
13 payer: authority,
14 name: 'My Programmable NFT',
15 uri: 'https://example.com/my-programmable-nft.json',
16 sellerFeeBasisPoints: 550, // 5.5%
17 tokenOwner: authority.address,
18 // Optional: add to collection (must verify separately)
19 // collection: { key: collectionMint.address, verified: false },
20});
21
22// Send both instructions in one transaction
23await sendAndConfirm({
24 instructions: [createIx, mintIx],
25 payer: authority,
26});
27
28console.log('Programmable NFT created:', mint.address);
下一步
本指南帮助您创建了一个基本的 NFT,从这里您可以前往 Token Metadata 程序 查看创建集合、将新 NFT 添加到集合以及您可以对 NFT 执行的各种其他交互。
