閱讀時間 11 分鐘
概覽
使用Candy Machine鑄造 10,000 個 NFT 固然有趣,但在許多情況下,我們可能需要鑄造單一 NFT(例如 1/1 的藝術品、音樂等)。創建 Solana 元數據標準的組織 Metaplex,最近開發了一些實用的 JS SDK,讓您能輕鬆地在終端機上創建 NFT。
您將負責的工作內容
在本指南中,您將使用 Metaplex Umi JS 函式庫,透過終端機在 Solana 的開發網(devnet)上鑄造帶有元資料的 NFT。我們將介紹 NFT 鑄造的三大關鍵步驟:
- 上傳圖片
- 上傳元資料
- Mint NFT
您需要準備的物品
Solana NFT 背景資訊
在開始開發我們的應用程式之前,讓我們先來談談 NFT 以及 Solana 的 NFT 架構。那麼,NFT 到底是什麼呢?非同質化代幣(Non-Fungible Token)實質上是一組儲存於區塊鏈上的資料,且與其他任何資料都截然不同。簡而言之,每一個 NFT 都是獨一無二的。在 Solana 上,我們透過使用 SPL 代幣程式(SPL Token Program)並創建一個總供應量為 1 的代幣來實現這一點。 此外,NFT 無法被分割,這意味著你無法擁有三分之一的 NFT(註:雖然有些進階的 NFT 協議涉及分數化,但通常 NFT 無法被拆分成更小的單位)。在 Solana 上,我們同樣透過 SPL 代幣程式將小數位數設定為 0(意即無法進行分數化)來實現這一點。
雖然從技術層面來看,發行供應量為 1 且小數位數為 0 的 SPL 代幣,確實屬於由其唯一鑄造 ID(Mint ID)定義的 NFT,但 SPL 代幣計畫在可儲存的資料類型與數量方面仍存在限制。此時,Metaplex 便應運而生。 Metaplex 元數據計畫為鏈上與鏈下元數據制定了標準。透過與鑄造帳戶關聯的「程式衍生地址」(Program Derived Address),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」參數初始化您的專案,以便為新套件採用預設值:
毛線 初始化 --是
#或
npm 初始化 --yes
建立一個已啟用 .json 匯入功能的tsconfig.json檔案:
tsc -init --resolveJsonModule true
最後,為您的上傳檔案建立一個資料夾:
mkdir uploads
請將一張圖片(.png 或 .jpg 格式)儲存至此資料夾,並命名為image.png。我們將使用這張像素感十足的絕美圖片:
安裝 Solana Web3 依賴項
在本次練習中,我們需要加入 Solana Web3 和 SPL 代幣函式庫。此外,我們將使用 Metaplex 的 JS SDK 以及 MPL 代幣元資料函式庫。請在終端機中輸入:
紗線 新增 @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults @metaplex-foundation/mpl-token-metadata @metaplex-foundation/umi-storage-mock
#或
npm 安裝 @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults @metaplex-foundation/mpl-token-metadata @metaplex-foundation/umi-storage-mock
建立錢包並領取 SOL 空投
您需要建立一個Solana 檔案系統錢包(密鑰對寫入wallet.json檔案中),並將一些 SOL 空投至該錢包。請在終端機中輸入:
solana-keygen new --靜默 --no-bip39-passphrase --outfile wallet.json
這將建立一個新錢包,並將其儲存至名為wallet.json 的檔案中。接著,您可以透過Quicknode Faucet或Solana Faucet 將一些 SOL 空投至此錢包。您可輸入以下指令來取得錢包地址:
Solana 地址 -k wallet.json
完成後,您應該能夠看到您的錢包餘額如下:
Solana 餘額 -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。
設定您的 Quicknode 端點
若要在 Solana 上進行開發,您需要一個 API 端點來連線至該網路。您可以使用公開節點,或自行部署並管理基礎架構;不過,若您希望將回應時間縮短 8 倍,不妨將繁重的工作交給我們處理。
了解為何超過 50% 的 Solana 專案都選擇 Quicknode,並在此註冊帳號。我們將使用一個 Solana Devnet 節點。
複製 HTTP 提供者連結:

在app.ts檔案中,於 import 語句下方,宣告您的 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 創建者 = createSignerFromKeypair(umi, creatorWallet);
umi.使用(金鑰對身分(creator));
umi.使用(mplTokenMetadata());
umi.使用(mockStorage());
定義 NFT 的特徵
我們將建立一個 nftDetail 一個包含我們希望納入 NFT 中的某些元資料的物件。建立一個新的 const, nftDetail,並包含以下屬性:
const nftDetail = {
name: "Quicknode Pixel",
symbol: "QP",
uri: "IPFS_URL_OF_METADATA",
royalties: 5.5,
description: 'Pixel infrastructure for everyone!',
imgType: 'image/png',
attributes: [
{ trait_type: 'Speed', value: 'Quick' },
]
};
您可在此自由填入自己的數值。
上傳您的圖片
在進行任何操作之前,我們需要先將用作 NFT 的圖片上傳至去中心化儲存平台。這是因為我們必須將 NFT 圖片的 URI 傳入 NFT 的元資料中。如果您已經有透過 URI 託管的圖片,請直接在您的 主頁 功能,並跳過此步驟。
為了上傳我們的圖片,我們將使用 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('Uploaded image:', imgUri);
return imgUri;
} catch (e) {
throw e;
}
}
如果你剛才仔細留意了我們先前的依賴項安裝與匯入步驟,你可能會注意到我們正在使用一個名為 @metaplex-foundation/umi-storage-mock. 顧名思義,這是一個模擬儲存系統,讓我們無需實際將檔案上傳至去中心化儲存平台,即可測試程式碼。這對於測試和除錯非常有用(而且使用完全免費!)。 Umi 的優點之一在於,它內建了用於儲存(及其他常見操作)的基礎泛型,這些泛型可以輕鬆替換為 Arweave 或 IPFS 等真實的儲存系統。這透過 上傳介面. 這表示您只需進行簡單的匯入與設定變更,即可將模擬儲存裝置替換為其他外掛程式。以下是 一份清單 現有的替代方案 上傳介面 選項。您只需導入相關套件,並將 umi.use(mockStorage()) 行至 umi.use(newStoragePlugin()).
真酷!
上傳元資料
元資料在某種程度上正是讓您的 NFT 獨一無二的關鍵。它包含圖片、任何特徵描述,以及將 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('Uploaded metadata:', metadataUri);
return metadataUri;
} catch (e) {
throw e;
}
}
在此,我們正在建立一個 JSON 物件,其中包含我們希望納入 NFT 中的元資料。接著,我們使用 Umi 上傳工具上傳此 JSON 物件, uploadJson 方法。該元數據物件包含我們 NFT 的名稱、描述、圖片 URI、屬性及特性。您可以稍作調整,但請確保其符合 適用於 NFT 的 Metaplex 元數據標準.
Mint NFT
與我們之前的函式一樣,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(`Created 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 應用程式
沒錯!你看到類似這樣的東西嗎?
ts-node 應用程式
上傳圖片:https://mockstorage.example.com/Quicknode Pixel
上傳的元資料:https://mockstorage.example.com/Km5iewgZoHUE1dIQJZx7
創建的 NFT:2dgA2xB4MebkQTMZeucoN1crDrPcLPaBryWChaUBcU6x
做得真好。
後續步驟與總結
現在你已經擁有一段方便且可重複使用的腳本,可以直接在終端機上鑄造 NFT 了!相當實用,對吧?想繼續深入探索嗎?以下提供幾個構想,讓你能基於剛學到的知識繼續深入探索:
- 請透過 SPL 代幣轉帳,將此 NFT 傳送至另一個錢包。(指南:《Solana 上的 SPL 代幣轉帳:完整指南》)
- 使用 Solana dApp Scaffold 建立一個 NFT 鑄造小工具。(指南:如何透過 Solana 錢包適配器與 Scaffold 將使用者連接到您的 dApp)注意:您必須使用錢包適配器身分,而非keypairIdentity來於前端環境中建立 Metaplex 實例。
如果你願意試試看,或者有任何問題想問我們,請告訴我們!歡迎在Discord和Twitter 上找到我們!
我們 ❤️ 您的回饋!
如果您有任何意見回饋或對新主題的建議,請告訴我們。我們非常樂意聽取您的意見。
