Workshop 7: Solana NFT

Bài viết này sẽ cung cấp đầy đủ thông tin giúp bạn hiểu rõ hơn về khái niệm NFT và Metaplex. Bên cạnh đó hướng dẫn bạn xây dựng program tương tác với NFT.

Workshop 7: Solana NFT

Bài viết này sẽ cung cấp đầy đủ thông tin giúp bạn hiểu rõ hơn về khái niệm NFT và Metaplex. Bên cạnh đó hướng dẫn bạn xây dựng program tương tác với NFT.

Metaplex

Metaplex là một tập hợp các công cụ, smart contract,...để gíup quá trình tạo và khởi chạy NFTs dễ dàng hơn. Hiện tại có ba dự án chính:

Trong bài này, chúng ta sẽ tìm hiểu tập trung chủ yếu vào Token Metadata để làm việc với NFT trên Solana

NFT

NFT là các token đặc biệt Non-Fungible. Chính xác hơn, NFTS trên Solana cũng chính là Mint Accounts với các đặc điểm sau:

  • Có supply bằng 1. Nghĩa là chỉ có duy nhất một token được lưu hành
  • Có decimals bằng 0, nghĩa là không thể có 0.5 tokens.
  • Không có mint authority, nghĩa là không có ai có thể đúc thêm token

Tóm lại, mã thông báo không thể được giao dịch với một thứ gì giống chính nó, đó là định nghĩa của Non-Fungible Token (NFT).

Token Metadata

Token metadata là chương trình siêu dữ liệu quan trong nhất khi giao dịch với NFT trên chuỗi khối Solana. Nó tập trung vào mục tiêu chính là đính kèm dữ liệu cho  Fungible or Non-Fungible Tokens trên Solana.

Để đạt được điều này, nó sử dụng Program Derived Addresses (PDAs) được suy ra từ Mint Accounts.

Metadata Account

Một thuộc tính qua trọng đối với Metadata Account đó là URI, nó dẫn đến một JSON file off-chain. Điều này được sử dụng để cung cấp các dữ liệu bổ sung là tuân thủ theo một tiêu chuẩn nhất định.

Tóm lại, mục tiêu của Metadata Account là cung cấp dữ liệu thực tế của NFT để biến nó thành tài sản kỹ thuật số hữu ích.

Master Edition Account

Ngoài ra, Token Metadata program còn cũng cấp một tài khoản đặc biệt khác gọi là Master Edition Account. Tài khoản này cũng là PDA được suy ra từ Mint Account.

Khi tạo tài khoản này, Token Metadata Program sẽ đảm bảo các tính chất Non-Fungible đã được nêu ở trên. Tuy nhiên cần lưu ý rằng, thay vì vô hiệu hoá Mint Authority, nó sẽ chuyển Mint Authority và Freeze Authority cho Master Edition PDA để đảm bảo rằng không có ai có thể mint hoặc freeze tokens mà không thông qua Token Metadata program.

Như vậy sự tồn tại của Master Edition account đóng vai trò là minh chứng cho tính  Non-Fungibility của Mint Account.

Printing Editions

Ngoài việc đóng vai trò đảm bảo tính Non-Fungibility, Master Edition còn đóng vai trò cho phép người dung in một hoặc nhiều bản sao của NFT.

Tính năng này đặc biệt hữu ích cho những người muốn cung cấp nhiều bản sao của 1/1 NFTs.

Master Edition account chứ tuỳ chọn Max Supply cho quy định số lượng NFT tối đa có thể được in theo cách đó. Nếu set bằng 0, tính năng printing sẽ bị tắt. Nêú set bằng None có thể in số lượng bản sao không giới hạn.

Mỗi NFT được in có Mint Account và Metadata Account của riêng nó với dữ liệu được sao chép từ bản gốc. Tuy nhiên thay vì có tài khoản Master Edition được đính kèm với Mint Account, Print NFTs sử dụng PDA account khác gọi là Edition Account. Tài khoản này theo dõi số ấn bản và ấn bản ốc mà nó bắt nguồn.

Accounts

Metadata

Seeds

Seed

Type

Description

Metadata

Literal: “metadata”

Tiền tố của PDA

Token Metadata Program

Program ID

Public key của program

Mint

Variable

Public key của Mint Account

Fields

Field

Offset

Size

Description

Key

0

1

The discriminator of the account as an enum. Equals to MetadataV1(4).

Update Authority

1

32

The public key that is allowed to update this account.

Mint

33

32

The public key of the Mint Account it derives from.

Name

65

36

The on-chain name of the token, limited to 32 bytes. For instance "Degen Ape #1 ".

Symbol

101

14

The on-chain symbol of the token, limited to 10 bytes. For instance "DAPE".

Uri

115

204

The URI of the token, limited to 200 bytes. This URI points to an off-chain JSON file that contains additional data following a certain standard. You can learn more about this JSON standard here. The JSON file can either be stored in a traditional server (e.g. using AWS) or using a permanent storage solution such as using Arweave.

Seller Fee Basis Points

319

2

(Indicative) The royalties shared by the creators in basis points — i.e. 550 means 5.5%. Whilst this field is used by virtually all NFT marketplaces, it is not enforced by the Token Metadata program itself.

Creators

321

~

(Optional) An array of creators and their share of the royalties. This array is limited to 5 creators. Note that, because the Creators field is an array of variable length, we cannot guarantee the byte position of any field that follows (Notice the tilde ~ in the fields below). Each creator contains the following fields.

Address

~

32

The public key of the creator

Verified

~

1

A boolean indicating if the creator signed the NFT. It is important to check this field to ensure the authenticity of the creator.

Share

~

1

(Indicative) The creator's shares of the royalties in percentage (1 byte) — i.e. 55 means 55%. Similarly to the Seller Fee Basis Points field, this is used by marketplaces but not enforced by the Token Metadata program.

Primary Sale Happened

~

1

(Indicative) A boolean indicating if the token has already been sold at least once. Once flipped to True, it cannot ever be False again. This field can affect the way royalties are distributed.

Is Mutable

~

1

A boolean indicating if the Metadata Account can be updated. Once flipped to False, it cannot ever be True again.

Edition Nonce

~

2

(Optional) A nonce used to verify the edition number of printed NFTs. It will only be set on Edition NFTs and not Master Edition NFTs.

Token Standard

~

2

(Optional) This enum captures the fungibility of the token. You can learn more about the token standard here.

Collection

~

34

(Optional) This field optionally links to the Mint address of another NFT that acts as a Collection NFT. It contains the following sub-fields.

Verified

~

1

A boolean indicating if the owner of the Collection NFT signed this NFT. It is important to check this field to ensure the authenticity of the collection.

Key

~

32

The public key of the Collection NFT's Mint Account

Uses

~

18

(Optional) This field can make NFTs usable. Meaning you can load it with a certain amount of "uses" and use it until it has run out. You can learn more about using NFTs here.

Use Method

~

1

An enum defining the use behaviour for the NFT. It can be one of the following: Burn, Multiple or Single.

Remaining

~

8

The remaining amount of uses.

Total

~

8

The total amount of uses allowed in the first place.

Collection Details

~

8

(Optional) This optional enum allows us to differentiate Collection NFTs from Regular NFTs whilst adding additional context such as the amount of NFTs that are linked to the Collection NFT. You can learn more about the sized collections here

Metaplex JavaScript SDK

SDK này giúp các nhà phát triển bắt đầu với các công cụ trên chuỗi cho Metaplex cung cấp. Nó cung cấp các tính năng cần thiết cho các và phát triển đồng thời cho phép bên thứ ba mở rộng các tính năng của nó thông qua các plugin

Lưu ý rằng SDK này vẫn đang trong quá trình phát triển tích cực. Điều này có nghĩa là một số API và interfaces có thể bị thay đổi từ phiên bản này sang phiên bản khác.

Cài đặt

npm install @metaplex-foundation/js @solana/web3.js

Điểm truy cập vào Javascript SDK là Metaplex,  cung cấp cho bạn quyền truy cập vào API.Nó chấp nhận Connection từ @solana/web3.js và sử dụng để giao tiếp với cluster.

import { Metaplex } from "@metaplex-foundation/js";
import { Connection, clusterApiUrl } from "@solana/web3.js";

const connection = new Connection(clusterApiUrl("mainnet-beta"));
const metaplex = new Metaplex(connection);

Ngoài ra, bạn có thể tuỳ chính nhà cung cấp bộ nhờ và wallet sử dụng khi tải nội dung lên. Bạn có thể thay đổi các trình điều khiển này bằng cách gọi phương thức use trên Metaplex.

Một ví dụ:

import { Metaplex, keypairIdentity, bundlrStorage } from "@metaplex-foundation/js";
import { Connection, clusterApiUrl, Keypair } from "@solana/web3.js";

const connection = new Connection(clusterApiUrl("mainnet-beta"));
const wallet = Keypair.generate();

const metaplex = Metaplex.make(connection)
    .use(keypairIdentity(wallet))
    .use(bundlrStorage());

Lưu ý rằng, bạn có thể tạo Metaplex instance bằng cách sử dụng Metaplex.make(...) thay vì new Metaplex(...) để làm cho API dễ đọc hơn.

Cách sử dụng

NFT module

Ví dụ đây là cách tìm nạp một NFT theo địa chỉ:

const nft = await metaplex.nfts().findByMint({ mintAddress });

NFT Module có thể được truy cập thông qua metaplex.nfts(). Bạn cũng có thể quan tâm đến tài liệu API của module này. Nó cung cấp các phương pháp sau:

findByMint

findByMint chấp nhận mint address là public key và trả về NFT object

const mintAddress = new PublicKey("ATe3DymKZadrUoqAMn7HSpraxE4gB88uo1L9zLGmzJeL");
const nft = await metaplex.nfts().findByMint({ mintAddress });

Trong dữ liệu trả về của Nft Object sẽ có JSON metadata nếu nó đã được tải lên. Chẳng hạn đây là cách truy cập URL hình ảnh của nó (Miễn là nó có trong metadata)

const imageUrl = nft.json.image;

Tương tự thông tin edition của NFT - bản gốc hay bản in - cũng có sẵn trên đối tượng thông qua thuộc tính edition. Loại của nó phụ thuộc vào việc nó là bản gốc hay bản in.

const editionAddress = nft.edition.address;

if (nft.edition.isOriginal) {
    const totalPrintedNfts = nft.edition.supply;
    const maxNftsThatCanBePrinted = nft.edition.maxSupply;
} else {
    const mintAddressOfOriginalNft = nft.edition.parent;
    const editionNumber = nft.edition.number;
}

findAllByMintList

Phương thức này nhận vào một danh sách địa chỉ mint và trả về một mảng NFTs. Tuy nhiên null sẽ được trả về nếu địa chỉ mint đã cũng cấp không liên kết với NFT.

const [nftA, nftB] = await metaplex.nfts().findAllByMintList({
    mints: [mintA, mintB]
});

NFTs truy xuất thông qua findAllByMintList không bao gồm JSON metadata bởi vì nó sẽ không hiệu qua nếu cung cấp một danh sách mint dài.

load

Vì lý do hiệu suất, nên khi tìm nạp hàng hoạt NFTs, bạn chỉ có thể nhận được Metadata thay vì JSON Metadata và thông tin ấn bản của NFT. Để có thể lất Nft Object từ Metatda bạn có thể sử dụng load như sau:

const nft = await metaplex.nfts().load({ metadata });

Điều này sẽ cung cấp cho bạn quyền truy cập vào json và edition của NFT tương tự trong NFT model.

findAllByOwner

Phương thức findAllByOwner chấp nhận một public key và trả về toàn bộ NFTs thuộc sử hữu của public key đó. Tương tự như findAllByMintList, kết quả trả về NFTs chỉ là Metadata, không bao gồm JSON Metadata vì lý do hiệu suất.

const myNfts = await metaplex.nfts().findAllByOwner({
    owner: metaplex.identity().publicKey
});

printNewEdition

Phương thức printNewEdition yêu cầu địa chỉ đúc của NFT gốc và trả về NFT hoàn toàn mới được in từ ấn bản gốc.

Đây là cách bạn sẽ in một phiên bản mới của NFT gốc

const { nft: printedNft } = await metaplex.nfts().printNewEdition({
    originalMint: originalNft.mint
});

Theo mặc định, nó sẽ in bănhf cách sử dụng Token Account của NFT gốc làm bằng chứng quyền sở hữu. Bạn có thể tuỳ chỉnh tất cả các tham số này bằng cách cung cấp chúng:

await metaplex.nfts().printNewEdition({
    originalMint,
    newMint,                   // Defaults to a brand-new Keypair.
    newUpdateAuthority,        // Defaults to the current identity.
    newOwner,                  // Defaults to the current identity.
    originalTokenAccountOwner, // Defaults to the current identity.
    originalTokenAccount,      // Defaults to the associated token account of the current identity.
});

Các bài viết liên quan

Workshop 1: Introduction to Solana

Workshop 2: Xây dựng giao diện tương tác với Solana

Workshop 3: Client interaction with common Solana programs (SPLT, Metaplex)

Workshop 4: Use the Rust programming language, Anchor

Workshop 5: Xây dựng chương trình đầu tiên với Anchor

Workshop 6: Xây dựng Program với PDAs và SPLT

Về Sentre Protocol

Sentre Protocol là nền tảng mở All-in-One hoạt động trên mạng lưới Solana, cung cấp DApp Store và giao thức mở giúp tích lũy thanh khoản. Với Sentre:

  • Người dùng có thể cài đặt các DApp yêu thích của mình và trải nghiệm thế giới DeFi trên một nền tảng duy nhất;
  • Lập trình viên và đối tác có thể phát hành DApp thông qua Sen Store, tận dụng tài nguyên có sẵn và tự do đóng góp cho nền tảng.