
Tạo một giao diện form trong Next.js để nhập thông tin metadata cho việc mint fungible token (FT).
- Tạo trang 
/mintvới form chứa các input: tên token, mô tả, link ảnh, vị trí (location), và địa chỉ ví nhận (tùy chọn). - Sử dụng state để quản lý dữ liệu nhập vào.
 - Hiển thị thông báo lỗi nếu input bắt buộc bị trống khi nhấn nút mint.
 - Định dạng giao diện bằng CSS.
 
Cách giải
- Tạo trang 
/mint:- Tạo file 
app/mint/page.tsxđể chứa form với các input cho metadata và địa chỉ ví nhận. - Sử dụng 
useStateđể quản lý dữ liệu nhập vào. 
 - Tạo file 
 - Xử lý input và lỗi:
- Thêm sự kiện 
onChangecho các input để cập nhật state. - Kiểm tra các input bắt buộc (tên, mô tả) khi nhấn nút mint và hiển thị thông báo lỗi nếu trống.
 
 - Thêm sự kiện 
 - Định dạng giao diện:
- Sử dụng inline CSS để tạo giao diện đẹp và rõ ràng.
 
 
Tạo file app/mint/page.tsx:
"use client";
import { useState } from "react";
export default function Mint() {
  const [metadata, setMetadata] = useState({
    name: "",
    description: "",
    image: "",
    location: "",
    recipient: "",
  });
  const [error, setError] = useState("");
  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setMetadata({ ...metadata, [e.target.name]: e.target.value });
  };
  const handleSubmit = () => {
    if (!metadata.name || !metadata.description) {
      setError("Vui lòng nhập tên và mô tả token");
      return;
    }
    setError("");
    console.log("Metadata:", metadata);
  };
  return (
    <div style={{ padding: "20px", textAlign: "center" }}>
      <h1>Mint Fungible Token</h1>
      <div style={{ maxWidth: "400px", margin: "0 auto" }}>
        <div style={{ marginBottom: "10px" }}>
          <label>Tên token:</label>
          <input
            type="text"
            name="name"
            value={metadata.name}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Mô tả:</label>
          <input
            type="text"
            name="description"
            value={metadata.description}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Link ảnh:</label>
          <input
            type="text"
            name="image"
            value={metadata.image}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Vị trí:</label>
          <input
            type="text"
            name="location"
            value={metadata.location}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Địa chỉ ví nhận (tùy chọn):</label>
          <input
            type="text"
            name="recipient"
            value={metadata.recipient}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <button
          onClick={handleSubmit}
          style={{
            padding: "10px 20px",
            backgroundColor: "#0070f3",
            color: "white",
            border: "none",
            borderRadius: "5px",
          }}
        >
          Mint Token
        </button>
        {error && <p style={{ color: "red", marginTop: "10px" }}>{error}</p>}
      </div>
    </div>
  );
}
Chạy npm run dev, truy cập http://localhost:3000/mint, nhập thông tin metadata, nhấn “Mint Token” để kiểm tra console log và thông báo lỗi nếu thiếu tên hoặc mô tả.
Tích hợp ví Cardano vào trang /mint để hiển thị số dư ADA sau khi kết nối.
- Sử dụng MeshJS để kết nối ví (như Eternl).
 - Hiển thị số dư ADA của ví sau khi kết nối.
 - Hiển thị thông báo lỗi nếu ví chưa kết nối.
 - Định dạng giao diện số dư.
 
Cách giải
- Cài đặt MeshJS:
- Cài đặt 
@meshsdk/corevà@meshsdk/react. 
 - Cài đặt 
 - Tích hợp ví:
- Sử dụng hook 
useWalletđể kết nối ví và lấy số dư. - Thêm nút “Connect Wallet” và hiển thị số dư sau khi kết nối.
 
 - Sử dụng hook 
 - Xử lý lỗi:
- Kiểm tra trạng thái kết nối ví trước khi lấy số dư.
 
 - Định dạng:
- Sử dụng inline CSS để hiển thị số dư.
 
 
Cài đặt:
npm install @meshsdk/core @meshsdk/react
Sửa file app/mint/page.tsx:
"use client";
import { useState, useEffect } from "react";
import { useWallet } from "@meshsdk/react";
export default function Mint() {
  const { connect, wallet, connected } = useWallet();
  const [metadata, setMetadata] = useState({
    name: "",
    description: "",
    image: "",
    location: "",
    recipient: "",
  });
  const [error, setError] = useState("");
  const [balance, setBalance] = useState("");
  useEffect(() => {
    if (connected) {
      async function fetchBalance() {
        try {
          const balance = await wallet.getBalance();
          const ada =
            balance.find((asset) => asset.unit === "lovelace")?.quantity || "0";
          setBalance(`${parseInt(ada) / 1000000} ADA`);
        } catch (err) {
          setBalance("Lỗi khi lấy số dư");
        }
      }
      fetchBalance();
    }
  }, [connected, wallet]);
  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setMetadata({ ...metadata, [e.target.name]: e.target.value });
  };
  const handleSubmit = () => {
    if (!connected) {
      setError("Vui lòng kết nối ví!");
      return;
    }
    if (!metadata.name || !metadata.description) {
      setError("Vui lòng nhập tên và mô tả token");
      return;
    }
    setError("");
    console.log("Metadata:", metadata);
  };
  return (
    <div style={{ padding: "20px", textAlign: "center" }}>
      <h1>Mint Fungible Token</h1>
      <div style={{ maxWidth: "400px", margin: "0 auto" }}>
        {!connected ? (
          <button
            onClick={() => connect("eternl")}
            style={{
              padding: "10px 20px",
              backgroundColor: "#0070f3",
              color: "white",
              border: "none",
              borderRadius: "5px",
              marginBottom: "20px",
            }}
          >
            Connect Wallet
          </button>
        ) : (
          <p style={{ marginBottom: "20px" }}>Số dư: {balance}</p>
        )}
        <div style={{ marginBottom: "10px" }}>
          <label>Tên token:</label>
          <input
            type="text"
            name="name"
            value={metadata.name}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Mô tả:</label>
          <input
            type="text"
            name="description"
            value={metadata.description}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Link ảnh:</label>
          <input
            type="text"
            name="image"
            value={metadata.image}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Vị trí:</label>
          <input
            type="text"
            name="location"
            value={metadata.location}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Địa chỉ ví nhận (tùy chọn):</label>
          <input
            type="text"
            name="recipient"
            value={metadata.recipient}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <button
          onClick={handleSubmit}
          style={{
            padding: "10px 20px",
            backgroundColor: "#0070f3",
            color: "white",
            border: "none",
            borderRadius: "5px",
          }}
        >
          Mint Token
        </button>
        {error && <p style={{ color: "red", marginTop: "10px" }}>{error}</p>}
      </div>
    </div>
  );
}
Chạy npm run dev, truy cập http://localhost:3000/mint, nhấn “Connect Wallet” để kết nối ví Eternl và hiển thị số dư ADA.
Tạo giao dịch mint fungible token (FT) trên client-side sử dụng MeshJS.
- Sử dụng MeshJS để mint FT dựa trên thông tin metadata từ form 
/mint. - Tạo policy ID từ địa chỉ ví người dùng bằng 
ForgeScript. - Kiểm tra ví đã kết nối và input hợp lệ trước khi mint.
 - Hiển thị Tx Hash sau khi mint thành công và liên kết đến CardanoScan.
 
Cách giải
- Xây dựng giao dịch mint:
- Sử dụng 
TransactionvàForgeScripttừ@meshsdk/coređể tạo policy ID và mint FT. - Lấy metadata và địa chỉ ví nhận từ state.
 
 - Sử dụng 
 - Ký và gửi giao dịch:
- Ký giao dịch bằng ví trình duyệt và submit lên blockchain.
 
 - Xử lý lỗi:
- Kiểm tra kết nối ví và input bắt buộc, hiển thị thông báo lỗi nếu cần.
 
 - Hiển thị Tx Hash:
- Hiển thị Tx Hash trong giao diện sau khi submit thành công.
 
 
Sửa file app/mint/page.tsx:
"use client";
import { useState, useEffect } from "react";
import { useWallet } from "@meshsdk/react";
import { Transaction, ForgeScript } from "@meshsdk/core";
export default function Mint() {
  const { connect, wallet, connected, walletAddress } = useWallet();
  const [metadata, setMetadata] = useState({
    name: "",
    description: "",
    image: "",
    location: "",
    recipient: "",
  });
  const [error, setError] = useState("");
  const [balance, setBalance] = useState("");
  const [txHash, setTxHash] = useState("");
  useEffect(() => {
    if (connected) {
      async function fetchBalance() {
        try {
          const balance = await wallet.getBalance();
          const ada =
            balance.find((asset) => asset.unit === "lovelace")?.quantity || "0";
          setBalance(`${parseInt(ada) / 1000000} ADA`);
        } catch (err) {
          setBalance("Lỗi khi lấy số dư");
        }
      }
      fetchBalance();
    }
  }, [connected, wallet]);
  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setMetadata({ ...metadata, [e.target.name]: e.target.value });
  };
  const handleSubmit = async () => {
    if (!connected) {
      setError("Vui lòng kết nối ví!");
      return;
    }
    if (!metadata.name || !metadata.description) {
      setError("Vui lòng nhập tên và mô tả token");
      return;
    }
    try {
      const recipient = metadata.recipient || walletAddress;
      const tokenName = metadata.name.replace(/s+/g, "_").toLowerCase();
      const forgeScript = ForgeScript.withOneSignature(walletAddress);
      const policyId = forgeScript.getPolicyId();
      const tx = new Transaction({ initiator: wallet });
      tx.mintAsset(forgeScript, {
        policyId,
        assetName: tokenName,
        quantity: "1",
        metadata: {
          name: metadata.name,
          description: metadata.description,
          image: metadata.image,
          location: metadata.location,
        },
      });
      tx.sendAssets({ address: recipient }, [
        { unit: `${policyId}${tokenName}`, quantity: "1" },
      ]);
      tx.setMetadata(721, {
        [policyId]: { [tokenName]: { ...metadata, name: metadata.name } },
      });
      const unsignedTx = await tx.build();
      const signedTx = await wallet.signTx(unsignedTx);
      const txHash = await wallet.submitTx(signedTx);
      setTxHash(txHash);
      setError("");
    } catch (err) {
      setError(`Lỗi: ${err.message}`);
    }
  };
  return (
    <div style={{ padding: "20px", textAlign: "center" }}>
      <h1>Mint Fungible Token</h1>
      <div style={{ maxWidth: "400px", margin: "0 auto" }}>
        {!connected ? (
          <button
            onClick={() => connect("eternl")}
            style={{
              padding: "10px 20px",
              backgroundColor: "#0070f3",
              color: "white",
              border: "none",
              borderRadius: "5px",
              marginBottom: "20px",
            }}
          >
            Connect Wallet
          </button>
        ) : (
          <p style={{ marginBottom: "20px" }}>Số dư: {balance}</p>
        )}
        <div style={{ marginBottom: "10px" }}>
          <label>Tên token:</label>
          <input
            type="text"
            name="name"
            value={metadata.name}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Mô tả:</label>
          <input
            type="text"
            name="description"
            value={metadata.description}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Link ảnh:</label>
          <input
            type="text"
            name="image"
            value={metadata.image}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Vị trí:</label>
          <input
            type="text"
            name="location"
            value={metadata.location}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Địa chỉ ví nhận (tùy chọn):</label>
          <input
            type="text"
            name="recipient"
            value={metadata.recipient}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <button
          onClick={handleSubmit}
          style={{
            padding: "10px 20px",
            backgroundColor: "#0070f3",
            color: "white",
            border: "none",
            borderRadius: "5px",
          }}
        >
          Mint Token
        </button>
        {error && <p style={{ color: "red", marginTop: "10px" }}>{error}</p>}
        {txHash && (
          <p style={{ color: "green", marginTop: "10px" }}>
            Mint thành công! Tx Hash:{" "}
            <a
              href={`https://preprod.cardanoscan.io/transaction/${txHash}`}
              target="_blank"
            >
              {txHash}
            </a>
          </p>
        )}
      </div>
    </div>
  );
}
Chạy npm run dev, truy cập http://localhost:3000/mint, kết nối ví, nhập thông tin metadata, nhấn “Mint Token” để mint FT và kiểm tra Tx Hash trên CardanoScan.
Tạo giao dịch mint fungible token (FT) trên server-side sử dụng MeshJS và Blockfrost.
- Tạo API route 
/api/cardano/mintđể xây dựng giao dịch unsigned cho minting FT. - Gửi metadata và địa chỉ ví nhận từ client.
 - Ký và submit giao dịch trên client-side.
 - Hiển thị Tx Hash sau khi mint thành công.
 
Cách giải
- Tạo API route:
- Tạo file 
app/api/cardano/mint/route.tsđể xây dựng giao dịch unsigned bằng MeshJS và Blockfrost. - Lấy UTxO từ Blockfrost dựa trên địa chỉ ví người gửi.
 
 - Tạo file 
 - Gửi request từ client:
- Sửa 
app/mint/page.tsxđể gửi POST request đến API route với metadata và địa chỉ ví nhận. 
 - Sửa 
 - Ký và submit:
- Nhận unsigned transaction từ server, ký bằng ví trên client, và submit.
 
 - Hiển thị kết quả:
- Hiển thị Tx Hash hoặc lỗi trong giao diện.
 
 
Tạo file app/api/cardano/mint/route.ts:
import { NextResponse } from "next/server";
import { Transaction, ForgeScript } from "@meshsdk/core";
import { BlockFrostAPI } from "@blockfrost/blockfrost-js";
export async function POST(request: Request) {
  try {
    const { sender, metadata, recipient } = await request.json();
    if (!sender || !metadata.name || !metadata.description) {
      return NextResponse.json(
        { error: "Thiếu thông tin sender hoặc metadata" },
        { status: 400 }
      );
    }
    const api = new BlockFrostAPI({ projectId: "preprodYourProjectIdHere" }); // Thay bằng project ID của bạn
    const utxos = await api.addressesUtxos(sender);
    const formattedUtxos = utxos.map((utxo) => ({
      input: { outputIndex: utxo.output_index, txHash: utxo.tx_hash },
      output: { address: utxo.address, amount: utxo.amount },
    }));
    const tokenName = metadata.name.replace(/s+/g, "_").toLowerCase();
    const forgeScript = ForgeScript.withOneSignature(sender);
    const policyId = forgeScript.getPolicyId();
    const tx = new Transaction();
    tx.mintAsset(forgeScript, {
      policyId,
      assetName: tokenName,
      quantity: "1",
      metadata: {
        name: metadata.name,
        description: metadata.description,
        image: metadata.image,
        location: metadata.location,
      },
    });
    tx.sendAssets({ address: recipient || sender }, [
      { unit: `${policyId}${tokenName}`, quantity: "1" },
    ]);
    tx.setMetadata(721, {
      [policyId]: { [tokenName]: { ...metadata, name: metadata.name } },
    });
    tx.setTxInputs(formattedUtxos);
    const unsignedTx = await tx.build();
    return NextResponse.json({ unsignedTx });
  } catch (error) {
    return NextResponse.json({ error: error.message }, { status: 500 });
  }
}
Sửa file app/mint/page.tsx:
"use client";
import { useState, useEffect } from "react";
import { useWallet } from "@meshsdk/react";
export default function Mint() {
  const { connect, wallet, connected, walletAddress } = useWallet();
  const [metadata, setMetadata] = useState({
    name: "",
    description: "",
    image: "",
    location: "",
    recipient: "",
  });
  const [error, setError] = useState("");
  const [balance, setBalance] = useState("");
  const [txHash, setTxHash] = useState("");
  useEffect(() => {
    if (connected) {
      async function fetchBalance() {
        try {
          const balance = await wallet.getBalance();
          const ada =
            balance.find((asset) => asset.unit === "lovelace")?.quantity || "0";
          setBalance(`${parseInt(ada) / 1000000} ADA`);
        } catch (err) {
          setBalance("Lỗi khi lấy số dư");
        }
      }
      fetchBalance();
    }
  }, [connected, wallet]);
  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setMetadata({ ...metadata, [e.target.name]: e.target.value });
  };
  const handleSubmit = async () => {
    if (!connected) {
      setError("Vui lòng kết nối ví!");
      return;
    }
    if (!metadata.name || !metadata.description) {
      setError("Vui lòng nhập tên và mô tả token");
      return;
    }
    try {
      const response = await fetch("/api/cardano/mint", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          sender: walletAddress,
          metadata,
          recipient: metadata.recipient,
        }),
      });
      const { unsignedTx, error } = await response.json();
      if (error) throw new Error(error);
      const signedTx = await wallet.signTx(unsignedTx);
      const txHash = await wallet.submitTx(signedTx);
      setTxHash(txHash);
      setError("");
    } catch (err) {
      setError(`Lỗi: ${err.message}`);
    }
  };
  return (
    <div style={{ padding: "20px", textAlign: "center" }}>
      <h1>Mint Fungible Token</h1>
      <div style={{ maxWidth: "400px", margin: "0 auto" }}>
        {!connected ? (
          <button
            onClick={() => connect("eternl")}
            style={{
              padding: "10px 20px",
              backgroundColor: "#0070f3",
              color: "white",
              border: "none",
              borderRadius: "5px",
              marginBottom: "20px",
            }}
          >
            Connect Wallet
          </button>
        ) : (
          <p style={{ marginBottom: "20px" }}>Số dư: {balance}</p>
        )}
        <div style={{ marginBottom: "10px" }}>
          <label>Tên token:</label>
          <input
            type="text"
            name="name"
            value={metadata.name}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Mô tả:</label>
          <input
            type="text"
            name="description"
            value={metadata.description}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Link ảnh:</label>
          <input
            type="text"
            name="image"
            value={metadata.image}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Vị trí:</label>
          <input
            type="text"
            name="location"
            value={metadata.location}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Địa chỉ ví nhận (tùy chọn):</label>
          <input
            type="text"
            name="recipient"
            value={metadata.recipient}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <button
          onClick={handleSubmit}
          style={{
            padding: "10px 20px",
            backgroundColor: "#0070f3",
            color: "white",
            border: "none",
            borderRadius: "5px",
          }}
        >
          Mint Token
        </button>
        {error && <p style={{ color: "red", marginTop: "10px" }}>{error}</p>}
        {txHash && (
          <p style={{ color: "green", marginTop: "10px" }}>
            Mint thành công! Tx Hash:{" "}
            <a
              href={`https://preprod.cardanoscan.io/transaction/${txHash}`}
              target="_blank"
            >
              {txHash}
            </a>
          </p>
        )}
      </div>
    </div>
  );
}
Chạy npm run dev, truy cập http://localhost:3000/mint, kết nối ví, nhập metadata, nhấn “Mint Token” để mint FT qua server-side. Kiểm tra Tx Hash trên CardanoScan.
Tạo giao dịch burn fungible token (FT) trên client-side sử dụng MeshJS.
- Tạo trang 
/burnvới form nhập policy ID, tên token, và số lượng để burn. - Sử dụng MeshJS để burn FT dựa trên thông tin nhập vào.
 - Kiểm tra ví đã kết nối và input hợp lệ trước khi burn.
 - Hiển thị Tx Hash sau khi burn thành công.
 
Cách giải
- Tạo giao diện:
- Tạo file 
app/burn/page.tsxvới form nhập policy ID, tên token, và số lượng. - Sử dụng 
useStateđể quản lý input. 
 - Tạo file 
 - Xây dựng giao dịch burn:
- Sử dụng 
TransactionvàForgeScripttừ@meshsdk/coređể burn FT. - Đặt số lượng âm để thực hiện burn.
 
 - Sử dụng 
 - Ký và gửi giao dịch:
- Ký giao dịch bằng ví trình duyệt và submit lên blockchain.
 
 - Xử lý lỗi và kết quả:
- Kiểm tra kết nối ví và input, hiển thị Tx Hash hoặc lỗi.
 
 
Tạo file app/burn/page.tsx:
"use client";
import { useState, useEffect } from "react";
import { useWallet } from "@meshsdk/react";
import { Transaction, ForgeScript } from "@meshsdk/core";
export default function Burn() {
  const { connect, wallet, connected, walletAddress } = useWallet();
  const [burnData, setBurnData] = useState({
    policyId: "",
    tokenName: "",
    quantity: "",
  });
  const [error, setError] = useState("");
  const [balance, setBalance] = useState("");
  const [txHash, setTxHash] = useState("");
  useEffect(() => {
    if (connected) {
      async function fetchBalance() {
        try {
          const balance = await wallet.getBalance();
          const ada =
            balance.find((asset) => asset.unit === "lovelace")?.quantity || "0";
          setBalance(`${parseInt(ada) / 1000000} ADA`);
        } catch (err) {
          setBalance("Lỗi khi lấy số dư");
        }
      }
      fetchBalance();
    }
  }, [connected, wallet]);
  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setBurnData({ ...burnData, [e.target.name]: e.target.value });
  };
  const handleSubmit = async () => {
    if (!connected) {
      setError("Vui lòng kết nối ví!");
      return;
    }
    if (!burnData.policyId || !burnData.tokenName || !burnData.quantity) {
      setError("Vui lòng nhập policy ID, tên token và số lượng");
      return;
    }
    try {
      const forgeScript = ForgeScript.withOneSignature(walletAddress);
      const tx = new Transaction({ initiator: wallet });
      tx.burnAsset(forgeScript, {
        policyId: burnData.policyId,
        assetName: burnData.tokenName,
        quantity: burnData.quantity,
      });
      const unsignedTx = await tx.build();
      const signedTx = await wallet.signTx(unsignedTx);
      const txHash = await wallet.submitTx(signedTx);
      setTxHash(txHash);
      setError("");
    } catch (err) {
      setError(`Lỗi: ${err.message}`);
    }
  };
  return (
    <div style={{ padding: "20px", textAlign: "center" }}>
      <h1>Burn Fungible Token</h1>
      <div style={{ maxWidth: "400px", margin: "0 auto" }}>
        {!connected ? (
          <button
            onClick={() => connect("eternl")}
            style={{
              padding: "10px 20px",
              backgroundColor: "#0070f3",
              color: "white",
              border: "none",
              borderRadius: "5px",
              marginBottom: "20px",
            }}
          >
            Connect Wallet
          </button>
        ) : (
          <p style={{ marginBottom: "20px" }}>Số dư: {balance}</p>
        )}
        <div style={{ marginBottom: "10px" }}>
          <label>Policy ID:</label>
          <input
            type="text"
            name="policyId"
            value={burnData.policyId}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Tên token:</label>
          <input
            type="text"
            name="tokenName"
            value={burnData.tokenName}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <div style={{ marginBottom: "10px" }}>
          <label>Số lượng:</label>
          <input
            type="number"
            name="quantity"
            value={burnData.quantity}
            onChange={handleInputChange}
            style={{ width: "100%", padding: "8px", marginTop: "5px" }}
          />
        </div>
        <button
          onClick={handleSubmit}
          style={{
            padding: "10px 20px",
            backgroundColor: "#0070f3",
            color: "white",
            border: "none",
            borderRadius: "5px",
          }}
        >
          Burn Token
        </button>
        {error && <p style={{ color: "red", marginTop: "10px" }}>{error}</p>}
        {txHash && (
          <p style={{ color: "green", marginTop: "10px" }}>
            Burn thành công! Tx Hash:{" "}
            <a
              href={`https://preprod.cardanoscan.io/transaction/${txHash}`}
              target="_blank"
            >
              {txHash}
            </a>
          </p>
        )}
      </div>
    </div>
  );
}
Chạy npm run dev, truy cập http://localhost:3000/burn, kết nối ví, nhập policy ID, tên token, và số lượng, nhấn “Burn Token” để burn FT và kiểm tra Tx Hash trên CardanoScan.
