如何在 Monad 上创建 Blinks

  • QuickNode
  • 发布于 2025-08-17 21:41
  • 阅读 50

本文介绍了如何在 Monad 测试网上使用 Blinks 创建 NFT 交互界面, 简化了 NFT 的铸造过程,用户可以通过点击链接,直接在钱包中签署交易完成 NFT 铸造。文章详细说明了 Blinks 的架构,并提供了在 Monad 链上搭建 NFT 铸造界面的步骤。

概述

Monad 是一个高性能、EVM 兼容的 Layer 1 区块链,旨在提供快速的交易、低廉的费用和可扩展性。 现在,将其与 Blinks 结合起来,Blinks 是与链上交互相关的可嵌入链接,你就拥有了一个强大的组合,可以吸引大众。

在本指南中,我们将引导你在 Monad 测试网上使用 Blinks 创建 NFT 界面。 首先,我们将介绍 Blinks 的架构设置方式,然后向你展示如何更新 Monad scaffold 存储库,以包括你的 NFT 铸造界面(可在你的网站或社交媒体上共享)。 让我们开始吧!

Blink 界面

你将要做什么

  • 了解 MonadBlinks
  • 使用 QuickNode 创建 Monad 测试网节点端点
  • 使用测试网 MON 代币为你的钱包充值
  • 克隆示例存储库并配置它,以在 Monad 测试网上创建一个 Blink,该 Blink 可以从 ERC-721 智能合约中铸造 NFT

你将需要什么

什么是 Monad?

Monad 由 Monad Labs 于 2022 年推出,专为高吞吐量(高达每秒 10,000 笔交易)和低成本交易(低于 1 美分)而设计。 它利用并行执行和优化的共识机制来增强可扩展性,同时保持与生态系统中流行的以太坊工具的兼容性。 这使其成为利用区块链的不同类型应用(如 NFT 和 DeFi)的理想平台。

什么是 Blinks?

Blinks 由 Dialect Labs 开发,代表 Blockchain Links。Blinks 是可共享的 URL,它将链上操作(如铸造 NFT)捆绑到一个可点击的链接中。 这消除了复杂集成的需要,允许开发人员在任何支持 URL 的地方(例如,社交媒体、网站)嵌入区块链交互。 对于用户而言,Blinks 通过一次点击简化了与区块链的交互,直接在他们的钱包中呈现一个可签名的交易。 自 2025 年 2 月起,Blinks 已在 Monad 的测试网上可用。

Blinks 深入探讨

Blinks 通过具有以下功能的提供者-客户端架构运行:

  • Blink Provider(后端):你的服务器,托管支持 Blink 体验的 API 端点
  • Blink Client:内省/解释 Blink URL 并呈现 Blink UI 的软件
  • URL Schema:连接提供者和客户端的标准化格式
  • 高级用例:表单:构建具有多个输入和高级输入类型的 Blinks
  • 高级用例:动作链:例如:在Token之间来回交换,UI 管理状态变化
  • 高级用例:表单:通过将引用键添加到你的 API 调用来跟踪交易的转换

Blinks 的核心功能是通过一个由两部分组成的 API 系统:

1. GET 路由

当首次访问 Blink URL 时,客户端会向提供者发送 GET 请求。提供者返回有关 Blink 的元数据,例如:

  • 标题和描述
  • 图标 URL
  • 可用操作
  • UI 参数(如输入表单)

此元数据允许客户端为你的 Blink 呈现一致的界面,而无需任何自定义集成。

2. POST 路由

当用户与 Blink 交互时(例如,单击“Mint NFT”按钮):

  • 客户端将包含用户输入和钱包地址的 POST 请求发送给提供者
  • 提供者构建一个区块链交易
  • 交易返回给客户端,客户端将其呈现给用户的钱包
  • 用户签署交易,然后将其广播到区块链

这种关注点分离允许交易逻辑保留在你的服务器上,而客户端处理钱包交互和 UI 呈现。

注意

请注意,本指南中提供的信息基于 Blinks 规范的当前状态。随着技术的发展,可能会引入新的功能和能力。请返回此处或查看 官方规范 以获取最新信息。

现在,对 Blinks 架构有了更好的了解,让我们继续讨论项目先决条件。

项目先决条件

从 QuickNode 多链水龙头获取 MON

为了在链上进行活动,与 Blink 交互的用户需要支付 gas 费用(在本例中为本地 MON 代币)。 由于我们使用的是 Monad 测试网,我们可以从 Multi-Chain QuickNode Faucet 获得一些测试 MON。

导航到 Multi-Chain QuickNode Faucet 并连接你的钱包(例如,MetaMask、Coinbase Wallet)或粘贴你的钱包地址以检索测试 MON。 请注意,要在以太坊主网上使用 EVM 水龙头,需要以太坊主网上的主网余额为 0.001 ETH。 你还可以通过 Twitter 或使用你的 QuickNode 帐户登录以获得奖励!

创建 Monad 端点

要与 Monad 通信,你需要访问一个节点。 虽然公共节点可用,但 QuickNode 提供的私有端点可提供更快、更稳定的性能。

  1. QuickNode 注册一个帐户。
  2. 转到“Endpoints”页面,然后单击“Create Endpoint”。
  3. 选择 Monad 作为链,Testnet 作为网络。
  4. 复制 HTTP Provider URL(例如,https://monad-testnet-xxx.quicknode.com/)并放在手边,因为你稍后需要它。

部署 NFT 合约 (ERC-721)

如果你尚未部署 NFT 合约,请查看本指南:如何创建和部署 ERC-721 NFT

在继续之前,请确保你的 NFT 合约可以执行以下操作,以便与我们的 Blink 完全兼容,否则需要对 SDK 代码进行一些细微更改。

  1. 具有一个 safeMint 函数,该函数接受 2 个参数(to 地址,amount(# Token))
  2. 它部署在 Monad 测试网上
  3. 任何人都可以 mint
  4. (推荐)元数据存储在 IPFS 上 + 一个函数,该函数返回给定Token ID 的元数据 URI(即,tokenURI
  5. 你拥有 NFT 合约地址,以便稍后在你的 Blink scaffold 中输入

你可以在 此处 查看完整的源代码示例。

接下来,我们将配置我们的 Monad scaffold 项目。

设置项目

对于这个项目,我们将使用 Monad Blinks Scaffold 模板。

首先,打开你的终端并导航到你要保存项目的位置。 接下来,运行命令以克隆 repo:

git clone https://github.com/dialectlabs/blink-starter-monad.git

接下来,导航到项目文件夹中并安装依赖项:

cd blink-starter-monad && npm install

现在,让我们更新 .env 文件。 打开它并更新它以包括你在上一步中创建的 QuickNode RPC URL。

MONAD_ENDPOINT_URL=https://api.quicknode.com/YOUR-KEY

现在,让我们更新 scaffold 代码,并使其与 NFT 铸造逻辑对齐。

Monad Blinks Scaffold

Monad Blinks scaffold 是一个预构建的项目,它提供了所有必要的组件、配置和样板代码,可以快速开始在 Monad 上构建 Blinks。 在本地使用此项目,我们可以看到我们的 Blink 在启动之前在 playground 环境中的行为方式。 这种内省非常有帮助,因为它允许开发人员在部署到生产环境之前在受控环境中测试和改进其应用程序的行为。

我们需要更新 scaffold 项目中的一些文件,以与 NFT 铸造界面对齐。 首先,我们将处理一些简单的更新,例如前端内容并将图像添加到项目中。

  • 更新你的文件 ( src/app/page.tsx) 以匹配 此处 的代码。
  • 将图像 ( nft-mint.png) 添加到你的 public 文件夹,该图像将显示在你的 Blink(你可以使用 此处)界面上。

接下来,让我们更新 API 路由中的核心逻辑以包括铸造过程。 在 src/app/actions/tip-mon 文件夹中,将文件夹从 tip-mon 重命名为 mint-nft。 然后,在 route.ts 文件中,我们将删除所有现有代码并按顺序包含以下每个代码片段。

1. 导入和基本设置

import { ActionGetResponse, ActionPostResponse, ActionError } from "@solana/actions";
import { serialize, http } from "wagmi";
import { parseEther, encodeFunctionData, createPublicClient } from "viem";
import { monad } from "@/monad";

const blockchain = "eip155:10143";
const NFT_CONTRACT_ADDRESS = "YOUR_NFT_ADDRESS"; // 输入你的 NFT 合约地址
const MINT_PRICE_MON = "YOUR_NFT_MINT_PRICE"; // 每个 NFT 的价格(以 MON 为单位)(根据你的智能合约进行调整)

const client = createPublicClient({
  chain: monad,
  transport: http(process.env.MONAD_ENDPOINT_URL),
});

首先,我们导入必要的库并设置我们的常量。 我们使用 CAIP-2 格式作为区块链 ID(即,一种更结构化的方式来表示链 ID),指定我们的 NFT 合约地址,并设置一个 publicClent 实例,以便我们稍后在生成交易时获取网络 gas 费用。

继续之前:确保你使用正确的值更新了 NFT_CONTRACT_ADDRESSMINT_PRICE_MON 变量。

2. 合约 ABI 和标头

在这里,我们为我们的 NFT 合约的 safeMint 函数定义了 ABI(应用程序二进制接口),该函数接受一个接收者地址。 我们还设置了 Blink 正常运行所需的 CORS 标头。 OPTIONS 端点是 CORS 预检请求所必需的。 没有它,Blink 将无法正确渲染。

将以下代码放在你的导入和客户端设置下的同一文件中。

const nftAbi = [
  {
    inputs: [
      { internalType: "address", name: "to", type: "address" },
      { internalType: "uint256", name: "amount", type: "uint256" }
    ],
    name: "safeMint",
    outputs: [{ internalType: "uint256[]", name: "", type: "uint256[]" }],
    stateMutability: "payable",
    type: "function",
  },
] as const;

const headers = {
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
  "Access-Control-Allow-Headers":
    "Content-Type, x-blockchain-ids, x-action-version",
  "Access-Control-Expose-Headers": "x-blockchain-ids, x-action-version",
  "Content-Type": "application/json",
  "x-blockchain-ids": blockchain,
  "x-action-version": "2.4",
};

export const OPTIONS = async () => {
  return new Response(null, { headers });
};

在这里,我们为我们的 NFT 合约的 safeMint 函数定义了 ABI(应用程序二进制接口),该函数接受一个接收者地址。 我们还设置了 Blink 正常运行所需的 CORS 标头。 OPTIONS 端点是 CORS 预检请求所必需的。 没有它,Blink 将无法正确渲染。

3. 估计 Gas

估计 gas 很重要,否则用户可能会为他们的交易支付过多的费用,因此我们需要创建一个辅助函数来检查网络 gas 费用并推荐我们用于优先费用的 gas 费用。

将此代码添加到 route.ts 文件中之前的代码(ABIHeaders)代码段下。

async function estimateGasFees() {
  const feeData = await client.estimateFeesPerGas();

  if (!feeData.maxFeePerGas || !feeData.maxPriorityFeePerGas) {
    throw new Error("Failed to retrieve gas fee data from the network");
  }

  return {
    maxFeePerGas: feeData.maxFeePerGas.toString(),
    maxPriorityFeePerGas: feeData.maxPriorityFeePerGas.toString(),
  };
}

4. GET 端点 - 获取用户详细信息

GET 端点为我们的 Blink 定义了 UI - 这是客户端(例如,社交媒体网站)将用于内省和渲染触发指定操作的按钮。 来自 GET 端点的响应使用来自 @solana/actions 的 ActionGetResponse 类型进行构造。 此类型确保返回的元数据包括所有必要的字段,以供 Blink 客户端正确渲染 UI,例如图标、标题、描述和用户可用的操作。 在本例中,我们已将其简化为显示单个“Mint NFT”按钮。

将此代码添加到 route.ts 文件中之前的代码(estimateGasFees)代码段下。

export const GET = async (req: Request) => {
  try {
    const response: ActionGetResponse = {
      type: "action",
      icon: `${new URL("/nft-mint.png", req.url).toString()}`,
      label: "",
      title: "",
      description: `1 ProtoMON = 0.0069420 MON`,
      links: {
        actions: [
          {
            type: "transaction",
            href: `/api/actions/mint-nft?amount={amount}`,
            label: "Mint NFT",
            parameters: [
              {
                name: "amount",
                label: `Enter MON amount in wei`,
                type: "number",
              },
            ],
          }
        ],
      },
    };

    return new Response(JSON.stringify(response), {
      status: 200,
      headers,
    });
  } catch (error) {
    console.error("Error in GET request:", error);
    const actionError: ActionError = {
      message: error instanceof Error ? error.message : "An unknown error occurred"
    };
    return Response.json(actionError, {
      status: 400,
      headers,
    });
  }
};

使用 ActionError 进行错误处理

如果在 GET 请求期间发生错误,则会捕获该错误并使用 ActionError 类型返回该错误。 此类型是一个简单的对象,具有消息属性,确保以标准化格式将错误传达给客户端。

5. POST 端点 - 交易创建

POST 端点包含用于解释用户输入的金额、交易生成和响应回用户的逻辑。 来自 POST 端点的响应使用 ActionPostResponse 类型进行构造。 此类型包括序列化的交易数据和消息,然后将其呈现给用户的钱包以进行签名。

POST 代码添加到 route.ts 文件中的 GET 端点逻辑下。

export const POST = async (req: Request) => {
  try {
    const requestBody = await req.json();
    const userAddress = requestBody.account;

    const url = new URL(req.url);
    const monAmount = url.searchParams.get("amount");

    if (!userAddress) {
      throw new Error("User address is required");
    }

    if (!monAmount) {
      throw new Error("MON amount is required");
    }

    const monValue = parseFloat(monAmount.replace(',', '.'));

    if (isNaN(monValue) || monValue <= 0) {
      throw new Error(`Invalid MON amount: ${monAmount}`);
    }

    const pricePerNFT = parseFloat(MINT_PRICE_MON);
    const numNFTs = Math.floor(monValue / pricePerNFT);

    if (numNFTs < 1) {
      throw new Error(`Amount too small. Minimum is ${MINT_PRICE_MON} MON for 1 NFT.`);
    }

    const actualMonAmount = (numNFTs * pricePerNFT).toFixed(8);
    console.log(`User entered ${monValue} MON, buying ${numNFTs} NFTs for ${actualMonAmount} MON`);

    const weiValue = parseEther(actualMonAmount);

    const data = encodeFunctionData({
      abi: nftAbi,
      functionName: "safeMint",
      args: [userAddress, BigInt(numNFTs)],
    });

    const gasEstimate = await estimateGasFees();

    const transaction = {
      to: NFT_CONTRACT_ADDRESS,
      data,
      value: weiValue.toString(),
      chainId: "10143", // Monad 测试网
      type: "0x2",
      maxFeePerGas: gasEstimate.maxFeePerGas,
      maxPriorityFeePerGas: gasEstimate.maxPriorityFeePerGas,
    };

    const transactionJson = serialize(transaction);

    const response: ActionPostResponse = {
      type: "transaction",
      transaction: transactionJson,
      message: `Minting ${numNFTs} NFT${numNFTs > 1 ? 's' : ''} for ${actualMonAmount} MON!`,
    };

    return new Response(JSON.stringify(response), {
      status: 200,
      headers,
    });
  } catch (error) {
    console.error("Error processing request:", error);
    const actionError: ActionError = {
      message: error instanceof Error ? error.message : "An unknown error occurred"
    };
    return Response.json(actionError, {
      status: 400,
      headers,
    });
  }
};

使用 ActionError 进行错误处理

GET 端点类似,POST 端点中的错误是使用 ActionError 类型处理的。 这确保了任何问题(例如无效的用户输入或 gas 估计失败)都会返回明确的消息,从而允许客户端向用户显示有意义的反馈。

POST 请求的工作方式摘要:

  • 从请求正文中获取用户地址 ( userAddress) 和输入金额 ( inputAmount)
  • 确认用户地址和金额都存在 ( if statements)
  • 通过编码 NFT 铸造函数调用、估计 gas 费用和构造完整的交易对象来构建交易 ( data)
  • 序列化交易 ( transactionJson) 以实现钱包兼容性
  • 返回成功消息或详细错误 ( response)

在本地运行 Blink

要启动服务器,请在项目根文件夹的终端中运行命令 npm run dev。 接下来,打开你的浏览器并导航到 http://localhost:3000。 你应该看到 NFT 铸造界面。

Blink 界面

尝试输入铸造 NFT 所需的最低金额。 在你的钱包中签署交易后,Blink 界面将使用交易详细信息进行更新:

铸造 NFT

你完成了! 你现在知道如何使用 Blinks、Wagmi、Viem 等开发人员工具创建自己的 Blink。

注册你的 Blink

让你的 Blink 上线以便与他人共享的下一步是在 Dialect 上注册它。

如果你想继续构建你刚刚学到的知识,请查看这些其他资源。

额外资源

最后的想法

你完成了! 你刚刚在 Monad 上创建了自己的 Blinks NFT 界面! 凭借现在了解如何使用最佳实践构建 Blink 的核心概念,你可以继续尝试其他类型的 Blinks 集成,例如创建 DeFi 操作(例如交换、staking、借贷或其他用例,例如在市场上展示列出的 NFT、众筹等)

如果你有问题或想法想要分享,请在 DiscordTwitter 上给我们留言!

我们 ❤️ 反馈!

如果你对新主题有任何反馈或要求,请 告诉我们。 我们很乐意收到你的来信。

  • 原文链接: quicknode.com/guides/mon...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
QuickNode
QuickNode
江湖只有他的大名,没有他的介绍。