
Bài 5: Xây Dựng DApp CIP-68 Hoàn Chỉnh (Next.js + FastAPI)
Chào mừng các bạn đến với Bài 5, chặng dừng chân cuối cùng và cũng là nơi mọi công sức của chúng ta đơm hoa kết trái!
Ở 3 bài trước, chúng ta đã đi từ lý thuyết CIP-68, viết Smart Contract bằng Aiken, cho đến việc dùng PyCardano chạy các script Mint, Update, Burn trên Terminal. Tuy nhiên, một sản phẩm Web3 thực thụ không thể bắt người dùng mở giao diện dòng lệnh (CLI) lên để gõ code được.
Hôm nay, chúng ta sẽ “khoác áo mới” cho dự án bằng cách xây dựng một DApp hoàn chỉnh:
-
Backend (FastAPI): Bọc các đoạn code PyCardano thành REST API.
-
Frontend (Next.js + React): Giao diện Web3 mượt mà cho phép người dùng kết nối ví (Nami, Eternl…), nhập thông tin và bấm nút để tương tác.
Mục Tiêu Bài Học
Trong bài này, bạn sẽ nắm được:
-
Kiến trúc phân tách Frontend – Backend trong một Cardano DApp.
-
Cách Backend (FastAPI) xây dựng giao dịch (Transaction Building) và trả về định dạng CBOR.
-
Cách Frontend (Next.js) kết nối ví người dùng (CIP-30) để ký (Sign) và gửi (Submit) giao dịch.
-
Hoàn thiện toàn bộ quy trình: Mint NFT động $\rightarrow$ Update Level $\rightarrow$ Burn trực tiếp trên giao diện web.
1. Kiến Trúc DApp (The Architecture)
Tại sao chúng ta lại cần cả Frontend lẫn Backend? Sao không code tất cả trên Frontend?
Lý do là vì Bảo mật và Hiệu năng.
-
Để thực hiện hành động Update (nâng cấp level NFT), Smart Contract của chúng ta yêu cầu chữ ký của Admin. Nếu để logic này trên Frontend, bạn sẽ phải lộ Private Key của Admin cho toàn bộ internet!
-
Do đó, kiến trúc chuẩn sẽ là:
-
Frontend: Nơi người dùng kết nối ví cá nhân, điền form, gọi API và ký phần của họ.
-
Backend: Nơi chứa Admin Key, xây dựng cấu trúc giao dịch (Mint/Update/Burn) bằng PyCardano một cách an toàn, sau đó mã hóa nó thành chuỗi CBOR và gửi về cho Frontend.
-
2. Xây Dựng Backend (FastAPI + PyCardano)
Trong thư mục backend/main.py, chúng ta sẽ khởi tạo một server FastAPI. Thay vì tự động Submit giao dịch như ở Bài 3, Backend giờ đây đóng vai trò là “Người thợ xây” (Transaction Builder).
Hãy xem cách API /api/mint hoạt động:
from fastapi import FastAPI
from pydantic import BaseModel
# ... import các hàm cip68 từ Bài 3 ...
app = FastAPI()
class MintRequest(BaseModel):
user_address: str
nft_name: str
image_url: str
initial_level: int
@app.post("/api/mint")
async def build_mint_tx(request: MintRequest):
# 1. Khởi tạo Builder và Metadata
builder = TransactionBuilder(context)
metadata = CIP68Metadata(
metadata={
b"name": request.nft_name.encode('utf-8'),
b"image": request.image_url.encode('utf-8'),
b"level": request.initial_level
}, version=1
)
# ... (Logic build transaction y hệt Bài 3: tạo cặp token, khóa Ref Token) ...
# 2. Xây dựng giao dịch nhưng KHÔNG KÝ (Unsigned Transaction)
tx_body = builder.build(change_address=Address.from_primitive(request.user_address))
# 3. Trả về mã CBOR thô cho Frontend
return {
"tx_cbor": tx_body.to_cbor().hex()
}
Các API cho /api/update và /api/burn cũng hoạt động theo cơ chế tương tự: Nhận yêu cầu $\rightarrow$ Tìm UTxO $\rightarrow$ Xây dựng giao dịch $\rightarrow$ Trả về mã Hex của giao dịch chưa ký.
3. Xây Dựng Frontend (Next.js + TailwindCSS)
Giao diện của chúng ta nằm trong thư mục template_frontend_cip68. Chúng ta sử dụng React, TypeScript và TailwindCSS để tạo ra một giao diện hiện đại.
Bước 1: Kết nối ví (Wallet Connect – CIP-30)
Để người dùng tương tác, chúng ta cần truy cập vào ví trình duyệt của họ (như Nami, Eternl) qua chuẩn CIP-30. File WalletContext.tsx sẽ lo việc này:
// Gọi API của ví để kết nối
const api = await window.cardano.nami.enable();
setWalletApi(api);
// Lấy địa chỉ ví của người dùng
const rawAddress = await api.getChangeAddress();
// Địa chỉ này sẽ được gửi lên Backend để Backend biết ai đang giao dịch
Bước 2: Xử lý quy trình Mint, Update, Burn
Đây là lúc “phép màu” kết hợp giữa Frontend và Backend xuất hiện. Hãy xem luồng logic khi người dùng bấm nút Mint trong component MintForm.tsx:
const handleMint = async () => {
// 1. Gửi thông tin (Tên, Hình ảnh) và Địa chỉ ví lên Backend FastAPI
const response = await axios.post("http://localhost:8000/api/mint", {
user_address: myWalletAddress,
nft_name: "Siêu Kiếm CIP68",
image_url: "ipfs://...",
initial_level: 1
});
// 2. Nhận giao dịch chưa ký (CBOR thô) từ Backend
const unsignedTxCbor = response.data.tx_cbor;
// 3. Gọi Ví của người dùng để KÝ giao dịch
const signedWitnesses = await walletApi.signTx(unsignedTxCbor, true);
// 4. Gắn chữ ký vào giao dịch và gửi lên Blockchain!
const txHash = await walletApi.submitTx(signedTxCbor);
alert(`Mint thành công! TX Hash: ${txHash}`);
};
Quy trình này cực kỳ an toàn: Backend xây dựng giao dịch chuẩn xác, nhưng người dùng vẫn có toàn quyền kiểm soát vì chính ví của họ mới là người bấm nút “Ký” (Sign) cuối cùng.
4. Trải Nghiệm End-to-End (Vòng Đời CIP-68 trên DApp)
Giờ hãy khởi động cả 2 server:
-
Backend: Chạy
python run_backend.py(cổng 8000) -
Frontend: Chạy
npm run dev(cổng 3000)
Mở trình duyệt và tận hưởng thành quả:
-
Kết Nối Ví: Bấm “Connect Wallet”, Nami pop-up hiện lên yêu cầu quyền truy cập.
-
Mint NFT: Điền tên “Hỏa Kiếm”, Level 1, chèn link ảnh và bấm Mint. Ví Nami sẽ yêu cầu bạn ký giao dịch. Sau vài giây, NFT xuất hiện trong ví của bạn!
-
Cập Nhật (Dynamic Update): Tại mục “My NFTs” (
NFTList.tsx), bạn sẽ thấy Hỏa Kiếm của mình. Bấm nút Update Level, nhập Level 2. Backend sẽ dùng Admin Key để ủy quyền, Frontend yêu cầu bạn ký phí giao dịch. Boom! NFT của bạn lập tức nhảy lên Level 2 trên blockchain. -
Hủy Bỏ (Burn): Nếu không thích nữa, bấm nút Burn. Cả Reference Token (trên Contract) và User Token (trong ví) sẽ bị thiêu rụi cùng lúc, trả lại lượng ADA bị khóa cho bạn.
Tổng Kết Chuỗi CIP-68
Xin chúc mừng! Bạn đã chính thức hoàn thành khóa đào tạo chuyên sâu về CIP-68 Dynamic Asset trên Cardano.
Hãy nhìn lại một chặng đường dài chúng ta đã đi qua:
-
Bài 1: Hiểu được sự khác biệt cốt lõi giữa tài sản tĩnh (CIP-25) và tài sản động (CIP-68) nhờ việc tách cặp token
Reference/Uservà sử dụngInline Datum. -
Bài 2: Tự tay viết Smart Contract bằng Aiken với logic Minting và Spending (CKV) chặt chẽ.
-
Bài 3: Điều khiển Smart Contract bằng mã off-chain Python/PyCardano.
-
Bài 4: Đóng gói toàn bộ thành một siêu phẩm Web3 DApp với Frontend Next.js và Backend FastAPI.
Kiến thức này là chìa khóa để bạn xây dựng các ứng dụng blockchain thế hệ mới: Từ GameFi (Nâng cấp trang bị/nhân vật), Identity (Cập nhật điểm uy tín DID), cho đến Real World Asset (Cập nhật giấy tờ tài sản thực).
Cảm ơn các bạn đã đồng hành. Chúc các bạn code thật vui và sớm ra mắt những siêu phẩm DApp của riêng mình!
Chi tiết nội source code của bài học các bạn có thể theo dõi tại đây!!!!
CIP-68 Dynamic NFT Implementation
