
Plug and Play Token Extensions
Giới thiệu
Token Extensions giúp việc tạo token có thể lập trình trên Solana trở nên dễ dàng. Các nhà phát triển có thể kết hợp hơn một chục Mint Extension và Account Extension bằng chương trình Token Extensions mới. Sau khi hoàn thành hướng dẫn, bạn sẽ tạo và tương tác với token có thể thay thế và không thể thay thế, token sinh lãi, token bị đóng băng, token mà bạn có toàn quyền kiểm soát (bao gồm cả việc chuyển chúng ra khỏi các tài khoản không thuộc sở hữu của bạn), đồng thời đóng tài khoản mint để thu hồi tiền.
Plug and Play Token Extensions là hướng dẫn có các ví dụ Solana Playground tương tác, giúp bạn tìm hiểu Token Extensions bằng TypeScript để tạo các token sau:
Mã dùng cho hướng dẫn này được điều chỉnh từ Hướng dẫn dành cho nhà phát triển Solana. Bạn có thể tìm thấy các script để tạo Token Extensions trong phần Tài nguyên bổ sung.
Tài khoản Token Extensions
Với các instruction mới, Token Extensions được xây dựng trên Token Program. Các tài khoản được tạo bằng cả hai chương trình có cấu trúc giống nhau ở phần độ dài ban đầu, cho đến khi các instruction của Token Program kết thúc và các instruction của Token Extensions bắt đầu. Nếu chưa quen với dữ liệu tài khoản, bạn có thể tìm hiểu về không gian tài khoản trong bài giới thiệu về Anchor. Tóm lại, các tài khoản trên Solana phải được tạo với không gian được phân bổ rõ ràng để lưu trữ dữ liệu on-chain. Từ không gian này, chúng ta có thể tính lượng lamport cần thiết để tài khoản được miễn phí thuê.
Đây là cách tạo tài khoản mint có các extension. Để phân bổ không gian cho Token Extensions, hãy dùng hàm getMintLen để lấy kích thước tài khoản mint có extension. Trong ví dụ NonFungibleToken.ts, hãy lấy độ dài mint của các loại Extension MetadataPointer và MintCloseAuthority.
NonFungibleToken.ts dòng 54:
// Size of Mint Account with extension
const mintLen = getMintLen([
ExtensionType.MetadataPointer,
ExtensionType.MintCloseAuthority,
]);Các extension Metadata và Metadata Pointer cho phép bạn lưu trữ và trỏ đến metadata mà không cần dựa vào giao thức của bên thứ ba. TokenMetadata là một interface từ @solana/spl-token-metadata, với các trường như updateAuthority, mint, name, symbol, uri và additionalMetadata. Độ dài metadata được xác định bằng hàm pack trên đối tượng metadata.
NonFungibleToken.ts dòng 60:
// Metadata to store in Mint Account
const metaData: TokenMetadata = {
updateAuthority: updateAuthority,
mint: mint,
name: "Solana Soldier",
symbol: "SOLD",
uri: "https://shdw-drive.genesysgo.net/G1Tzt42SDqCV3x9vPY5X826foA8fEk8BR4bB5wARh75d/OIG2.jpg",
additionalMetadata: [["armor", null]],
};
// Size of metadata
const metadataLen = pack(metaData).length;
// Size of MetadataExtension 2 bytes for type, 2 bytes for length
const metadataExtension = TYPE_SIZE + LENGTH_SIZE;Cộng độ dài mint, extension metadata và độ dài metadata để xác định số lamport tối thiểu cần thiết cho Tài khoản Mint.
NonFungibleToken.ts dòng 75:
// Minimum lamports required for Mint Account
const lamports = await connection.getMinimumBalanceForRentExemption(
mintLen + metadataExtension + metadataLen
);Instruction của Token Extensions
Các thư viện Solana như @solana/spl-token và @solana/spl-token-metadata bổ sung hỗ trợ TypeScript cho chương trình Token Extensions. Trước tiên, hãy tạo một tài khoản với lượng không gian và lamport miễn phí thuê phù hợp bằng SystemProgram từ @solana/web3.js.
NonFungibleToken.ts dòng 80:
// Instruction to invoke System Program to create new account
const createAccountInstruction = SystemProgram.createAccount({
fromPubkey: payer.publicKey, // Account that will transfer lamports to created account
newAccountPubkey: mint, // Address of the account to create
space: mintLen, // Amount of bytes to allocate to the created account
lamports, // Amount of lamports transferred to created account
programId: TOKEN_2022_PROGRAM_ID, // Program assigned as owner of created account
});Tiếp theo, chúng ta có thể tạo các instruction để chỉ định mint. Các instruction sau phải được thực thi trước khi gọi initializeMint. Các instruction trước khi mint được dùng trong Plug and Play gồm:
- Khởi tạo Metadata Pointer: createInitializeMetadataPointerInstruction
- Khởi tạo quyền đóng mint: createInitializeMintCloseAuthorityInstruction
- Khởi tạo mint không thể chuyển nhượng: createInitializeNonTransferableMintInstruction
- Khởi tạo đại diện vĩnh viễn: createInitializePermanentDelegateInstruction
- Khởi tạo mint token sinh lãi: createInitializeInterestBearingMintInstruction
Các tài khoản metadata có thể được khởi tạo và cập nhật độc lập với initializeMint. Tuy nhiên, Metadata Pointer phải được khởi tạo trước mint. Thứ tự instruction trong giao dịch quyết định thứ tự thực thi. Hãy tạo tài khoản mint, khởi tạo metadata pointer, rồi khởi tạo quyền đóng mint bằng khóa công khai của mint. Sau đó, khởi tạo mint và các tài khoản metadata, rồi cập nhật metadata bổ sung.
NonFungibleToken.ts dòng 135:
transaction = new Transaction().add(
createAccountInstruction,
initializeMetadataPointerInstruction,
initializeMintCloseAuthorityInstruction,
initializeMintInstruction,
initializeMetadataInstruction,
updateFieldInstruction
);Các tệp nonFungibleToken.ts, soulboundToken.ts, interestBearingToken.ts và delegateToken.ts sử dụng cùng một cấu trúc để tạo token, chỉ khác ở các extension và instruction được dùng.
Quy trình bắt đầu bằng việc nhập tất cả hàm cần thiết từ các thư viện Solana tương ứng, xác định payer và tạo địa chỉ mint. Sau đó, xác định không gian và số lamport cần thiết cho địa chỉ mint với các token extension mong muốn. Tạo instruction bằng các thư viện @solana/spl-token và @solana/spl-token-metadata, thêm chúng vào một giao dịch, gửi giao dịch đến mạng và xác thực kết quả.
Các thao tác với token như chuyển và đốt có thể được dùng trên nhiều token extension khác nhau. Token có Metadata Extension có thể dùng lần lượt các instruction createUpdateFieldInstruction và createRemoveKeyInstruction để cập nhật hoặc xóa metadata.
Plug and Play
Trong Solana Playground, client chứa các hàm cần thiết để tương tác với Token Extensions. Ví dụ, token linh hồn sử dụng các extension Non-Transferable và Metadata để tạo một NFT linh hồn. Các hàm để tạo và tương tác với token nằm trong cùng một tệp và có thể được nhập (trong Solana Playground, bạn phải sao chép và dán mã thay vì nhập).
Tệp quest.ts cho phép bạn chơi Solana Soldier. Ngoài ra, hãy chạy từng tệp chứa token extension để xem chức năng cụ thể của chúng. Playground Wallet cần Devnet SOL để chạy nhiệm vụ. Vòi Solana Devnet của chúng tôi cũng có thể cấp Devnet SOL qua airdrop.
Nhiệm vụ bắt đầu bằng việc tạo một Solana Soldier, một NFT mà payer (pg.wallet.keypair) có quyền đóng mint — cho phép payer đóng tài khoản mint và thu hồi SOL. Cơ chế này hữu ích cho các ứng dụng muốn thu hồi SOL từ những tài khoản không còn hoạt động.
Sau khi tạo Solana Soldier, hãy dùng địa chỉ mint của nhân vật để cập nhật metadata của NFT. Hãy nâng cấp áo giáp của chiến binh thành iron. Có thể tìm thấy các hàm getMetadata, updateMetadata và removeMetadata trong tệp NonFungibleToken.ts, bắt đầu từ dòng 167. Các hàm này có thể được gọi cho những tài khoản mint sử dụng Metadata Extension. Để đơn giản, các hàm metadata sẽ chỉ được đưa vào tệp NonFungibleToken.ts.
Tiếp theo là lúc bắt đầu lên cấp. Một token sinh lãi sẽ đại diện cho cấp độ của Solana Soldier. Từ InterestBearingToken.ts, hãy nhập createInterestBearingToken và dùng instruction này để tạo token. Tiền lãi trong tài khoản sẽ tăng theo tỷ lệ được đặt ở dòng 43 trong InterestBearingToken.ts. Có thể dùng hàm amountToUiAmount để xác định số lượng token đã tích lũy lãi. Tiền lãi tích lũy theo thời gian và chúng ta có thể gọi amountToUiAmount để kiểm tra cấp độ của Solana Soldier.
Khi chiến binh bắt đầu lên cấp, họ cần nhận một nhiệm vụ. Nhiệm vụ được đại diện bằng một token linh hồn — chiến binh không thể chuyển token này (hãy thử bắt lỗi bằng cách gọi hàm chuyển), và cách duy nhất để loại bỏ nhiệm vụ là đốt token. Thay vì từ bỏ nhiệm vụ, hãy xem nội dung của nó. Gợi ý: kiểm tra metadata!
Sau khi bạn đọc nhiệm vụ, hướng dẫn Plug and Play sẽ triển khai một đội quân đến địa chỉ token. Solana Soldier phải có khả năng triệu hồi đội quân trở lại payer sau khi token được triển khai. Token Extensions biến điều này thành hiện thực bằng cách cung cấp quyền đại diện. Quyền đại diện có thể chuyển và đốt token bất kể ai sở hữu chúng. Hãy đặt đại diện vĩnh viễn thành một keypair mà bạn có quyền truy cập; keypair này cần ký để đốt và chuyển token.
Token ủy quyền sẽ đại diện cho Solana Army. Tạo token ủy quyền bằng createDelegateTokens từ dòng 33 của DelegateToken.ts vào tài khoản token của kẻ địch. Khi token được mint, Solana Army và kẻ địch bước vào một trận chiến giả định. Sau trận chiến, hãy triệu hồi binh lính từ tài khoản của kẻ địch bằng hàm transferDelegateTokens trong dòng 176 của DelegateTokens.ts.
Lưu ý rằng không phải tất cả binh lính đều được triệu hồi khỏi địa chỉ của kẻ địch. Hãy giả định họ đã hy sinh. Dùng hàm burn từ @solana/spl-token để đốt số token còn lại trong tài khoản token của kẻ địch (sourceTokenAccount).
Sau chiến thắng, nhiệm vụ của Solana Soldier kết thúc. Hàm closeAccount từ @solana/spl-token được dùng để đóng tài khoản và hoàn lại phí thuê. Các Token Extensions không được đề cập trong bài viết này gồm chuyển giao bí mật, phí chuyển giao và transfer hook. Hầu hết token extension đều có thể kết hợp với nhau, ngoại trừ một số trường hợp như transfer hook và token không thể chuyển nhượng. Các Solana Playground tham chiếu cho những Token Extensions được đề cập trong hướng dẫn này có liên kết ở phần Tài nguyên bổ sung.
Kết luận
Lấy cảm hứng từ CryptoZombies, hướng dẫn Plug and Play này trình bày những kiến thức cơ bản về cách tạo các Token Extensions phổ biến bằng cách kết hợp nhiều extension. Hướng dẫn thể hiện khả năng kết hợp của Token Extensions qua trải nghiệm chơi game thực hành. Các ví dụ có thể được dùng theo kiểu Plug and Play hoặc làm tài liệu hướng dẫn cho những nhà phát triển tự viết token. Từ việc xác định kích thước tài khoản đến sắp xếp instruction, các ví dụ cung cấp quy trình tinh gọn để tạo tài khoản với Token Extensions. Nếu thấy trải nghiệm học tập được trò chơi hóa này hữu ích, hãy chia sẻ phản hồi trên Discord của chúng tôi hoặc gắn thẻ @helius trên X.
Tài nguyên bổ sung
- Bắt đầu với Token Extensions
- Solana Soldier trên Solana Playground
- Quyền đóng mint | Solana Playground
- Token không thể chuyển nhượng | Solana Playground
- Token sinh lãi | Solana Playground
- Đại diện vĩnh viễn | Solana Playground
- Metadata | Solana Playground
- GitHub của Token Extensions
- GitHub của Token Program
- GitHub của SPL
Bài viết liên quan
Đăng ký nhận tin từ Helius
Luôn cập nhật những thông tin mới nhất về phát triển Solana và nhận thông báo khi chúng tôi đăng bài


