Solana框架:在Farcaster上铸造cNFT

  • Helius
  • 发布于 2024-03-08 19:36
  • 阅读 13

本文介绍了去中心化社交媒体平台Farcaster及其支持Solana的创新,尤其是如何通过框架技术创建交互应用和铸造压缩NFT (cNFT)。探索了Farcaster的用户拥有权、可互操作性,以及如何使用Helius Mint API进行框架创建和Solana地址验证。此外,提供了详细的代码示例和运行步骤,适合开发者入门。

12分钟阅读 , 2024年3月6日

这篇文章讲了什么?

去中心化社交媒体标志着一种重大转变,旨在赋予用户更大的隐私和对在线数据的控制。与传统社交媒体平台不同,去中心化网络使个人能够直接管理他们的社交图谱和数字身份。像Farcaster这样的平台处于前沿,创建了抗审查的网络,促进了跨各种平台的开放、可互操作的沟通。Farcaster中的一个关键创新是引入了frames —— 将常规社交媒体帖子转变为完全成熟的应用程序 —— 以丰富在线社交体验。

本文将探讨Farcaster及其最近对Solana的支持。我们将覆盖Farcaster是什么,frames是什么,以及如何验证Solana地址。接下来,我们将通过一个简短的教程,创建一个向用户的已验证Solana地址铸造cNFT的frame,使用Helius Mint API。本教程假设读者对TypeScriptNext.js有一定的基础。

什么是Farcaster?

Farcaster是一个足够去中心化的社交网络,利用Ethereum网络。它提供了一个公共平台,类似于Twitter和Reddit等流行社交网络,用户可以创建个人资料,分享帖子(称为casts),并关注其他用户。使Farcaster与众不同的是它对用户拥有权和可移植性的强调——用户拥有他们的帐户和与他人的关系。他们可以在不同的应用程序之间移动,同时保持他们的数字身份和社交图谱。

什么是Frames?

Farcaster Frames

Frames使开发者能够将任何cast转变为互动应用程序。通过扩展OpenGraph标准,它们将静态嵌入转变为动态、互动的体验。这使用户能够在任何Farcaster客户端,包括Warpcaster,创建诸如投票、实时动态或互动画廊等功能。从本质上讲,frame是一组<meta>标签,作为HTML页面的<head>部分返回。如果页面包含所有必需的frame属性,Farcaster应用将渲染该页面为frame。Frame Specification概述了这些必需的属性。例如,一个初始frame必须:

  • 在HTML <head>部分返回有效的frame
  • 在用户通过浏览器访问frame时返回有效的HTML <body>
  • 在初始frame中不包含动态内容,因为Farcaster客户端会对其进行缓存
  • 不包含fc:frame:state标签

在Farcaster上验证Solana地址

在Farcaster上验证Solana地址

Farcaster最近添加了对Solana地址的支持。这意味着开发者可以构建与用户的Solana钱包交互的frames。在支持上线不到24小时的时间里,超过9328个独特的Farcaster FID已验证Solana地址

用户可以通过以下方式验证他们的Solana地址:

  • 导航到设置
  • 点击已验证的地址并点击“验证地址”按钮
  • 连接他们的Solana钱包,并签署消息以证明所有权

请注意,目前唯一支持的钱包是Phantom

教程:创建一个铸造cNFT的Frame

在本文中,我们将创建一个Frame,使得拥有已验证Solana地址的用户可以铸造压缩NFT(cNFT)。我们将使用frames.js,一个用于构建和调试frames的Next.js模板,启动该项目。我们将使用Coinbase的OnchainKit,特别是Frame Kit,在用户与frame交互时获取Farcaster用户的信息。然后,我们将这些数据传入Helius Mint API,为用户的Solana钱包铸造以下cNFT

Mint cNFT

设置我们的Frame

使用frame.js创建frame非常简单,只需克隆启动模板即可。只需运行以下命令,将<name>替换为你希望克隆模板的新文件夹名称:

npx degit github:framesjs/frames.js/examples/framesjs-starter#main <name>

我决定将我的目录命名为helius-frame,因此将<name>替换为<helius-frame>。接下来,切换到新目录(例如,cd helius-frame),并通过yarn install命令安装必要的依赖项。下载完成后,运行yarn dev以运行开发服务器。在浏览器中访问http://localhost:3000来查看以下内容:

debug hyperlink

单击调试超链接,我们将进入http://localhost:3000/debug

local host debug

这很有帮助,因为我们可以在本地测试我们的frame,而无需发布它。例如,我们可以登录以测试按钮、冒充其他用户并模拟集线状态。Warpcaster还有一个出色的Frame Validator工具来验证frames。接下来,我们将纯粹出于个人喜好,使用Frame Validator工具进行测试。

接下来,运行yarn install安装模板的相关依赖。我们还需要运行yarn install @coinbase/onchainkit以安装OnchainKit。

我们将以如下方式重新安排项目的文件夹:

  • 删除examples文件夹——虽然示例提供了构建frames的宝贵见解,但它们对我们的目标没有必要。删除该文件夹可减少项目膨胀。但我强烈建议浏览它们,以寻找构建常见frames的替代方法。
  • app目录中创建一个api文件夹。此步骤与Next.js的API路由的约定一致,提供了应用程序前端和后端之间的清晰区分。然后,将frames文件夹(及其内容包括route.ts)移入新的api文件夹。
  • app目录中创建一个utils文件夹。在此新文件夹中创建一个mint.ts文件——这就是我们将放置cNFT铸造逻辑的地方。

我们现在终于可以开始构建我们的frame了!

编辑我们的Frame

layout.tsx

我们将从layout.tsx文件开始。删除所有内容并用以下代码替换:

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (

      {children}

  );
}

RootLayout组件采取简约的方式,将整个应用程序包裹在一个一致的布局结构中。它灵活且设计为可重用的。通过从这个简约布局开始,开发者可以根据需要使用此文件作为构建和自定义自己的frames的模板。

请注意,通过更改layout.tsx文件,你在本地使用调试器时会遇到问题。编辑layout.tsx并 non-mandatory。然而,我们这样做是为了引入应用程序的元数据。在page.tsx中引入元数据也是可以的。

page.tsx

删去page.tsx的内容,用以下内容替换:

import type { Metadata } from "next";
import { getFrameMetadata } from "@coinbase/onchainkit";

const baseURL = "https://helius-frame.vercel.app/";

const frameMetadata = getFrameMetadata({
  image: {
    src: `${baseURL}/default.jpg`,
    aspectRatio: "1:1",
  },
  buttons: [
    {
      label: "点击在Solana上铸造cNFT!",
      action: "post",
    },
  ],
  postUrl: `${baseURL}api/frames`,
});

export const metadata: Metadata = {
  title: "在Solana上铸造cNFT",
  description: "使用Helius Mint API向你的已验证Solana地址铸造cNFT",
  openGraph: {
    title: "在Solana上铸造cNFT",
    description: "使用Helius Mint API向你的已验证Solana地址铸造cNFT",
    images: ["https://helius-frame.vercel.app/default.jpg"],
  },
  other: {
    ...frameMetadata,
  },
};

export default function Page() {
  return (

      在Farcaster上使用Helius Mint API铸造cNFT

        由0xIchigo构建

        GitHub Repo

  );
}

上述代码设置了我们的初始frame,它将在网络服务器上的某个URL上托管。在我的情况下,初始frame托管在Vercel上,地址为https://helius-frame.vercel.app/——我们将在本教程的后面讨论如何使用Vercel进行部署。

首先,我们从Next.js导入Metadata类型,以便为该文件中的metadata导出进行类型定义。我们还从@coinbase/onchainkit导入getFrameMetadata。然后,我们定义应用程序的基本URL,以减少重复代码。

接着,我们调用getFrameMetadata来配置我们初始frame的元数据。此元数据包括:

  • 一张图像(即src),作为frame的视觉元素,宽高比为1:1
  • 一个标签为“点击在Solana上铸造cNFT!”的按钮,当被点击时,会向指定的postUrl(即${baseURL}api/frames)发送POST请求。这个动作启动铸造过程。

然后,我们导出一个metadata对象,包括页面的标题和描述,OpenGraph元数据(即openGraph),以及之前定义的frameMetadata展平到other属性中。

最后,page定义并导出默认页面组件。我们返回一个简单的h1,提示铸造cNFT。这是因为Farcaster要求我们返回一些HTML——主要交互是通过frames管理的,而不是直接访问该网站。然而,如果用户点击进入,网站上仍需要存在一些东西。

mint.ts

mint.ts中粘贴以下代码:

const url = `Get a URL at dev.helius.xyz`;

export const mintCompressedNFT = async (address: string) => {
    const response = await fetch(url, {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
        },
        body: JSON.stringify({
            jsonrpc: "2.0",
            id: "frames-sol-mint",
            method: "mintCompressedNft",
            params: {
                name: "Solana Soldier",
                symbol: "HELIUS",
                owner: address,
                description: "由Solana最受欢迎的RPC节点、API、Webhook和开发工具支撑的去中心化战士",
                attributes: [
                    {
                        trait_type: "RPCs",
                        value: "快速",
                    },
                    {
                        trait_type: "公司",
                        value: "Helius"
                    },
                ],
                imageUrl: "https://shdw-drive.genesysgo.net/HmvVwYAy7cxWECLbu2cjWBSHysVoriTqgdugyePVg3rY/cnftmint.jpg",
                externalUrl: "https://www.helius.dev/",
                sellerFeeBasisPoints: 6900,
            },
        }),
    });

    const data = await response.json();
    console.log(`data: ${JSON.stringify(data, null, 2)}`);

    if (!response.ok) {
        throw new Error(`响应不正确 - ${response.status}`);
    }

    if (!data.result || !data.result.assetId) {
        throw new Error(`响应未包含预期的data.result.assetId字段`);
    }

    return data.result;
};

mintCompressedNFT工具函数是我们应用程序的关键,因为它会将预定义的cNFT铸造到指定的地址。我们正在使用Helius Mint API来创建一个简单、可重用和异步的函数,封装cNFT铸造过程。我们必须请求我们的Helius General RPC URL,定义为url。如果你还没有一个,请访问dev.helius.xyz生成一个免费的RPC URL用于url。请注意,我的存储库使用我自己的SecureRPC URL——小心泄露你的API密钥,考虑使用代理。关于请求本身,完整的请求架构分解可以在这里找到。同样需要注意的是,我已将cNFT的图像上传到ShdwDrive,因为在撰写本文时,Farcaster尚未添加完整交易支持——Helius Mint API处理上传离线元数据到Arweave,只要提供了签名者即可。

该功能还包括强大的错误处理,以确保在铸造过程中任何问题都能被捕获并报告。它还记录响应数据以便于调试。

route.ts

api/frames/route.ts中粘贴以下代码:

import { NextRequest, NextResponse} from "next/server";
import { getFrameMessage, getFrameHtmlResponse } from "@coinbase/onchainkit/frame";
import { mintCompressedNFT } from "../../utils/mint";

const baseURL = "https://helius-frame.vercel.app/";

export async function POST(req: NextRequest): Promise {
    const body = await req.json();

    // 验证frame消息并提取用户ID
    const { isValid, message } = await getFrameMessage(body, {
        neynarApiKey: "NEYNAR_ONCHAIN_KIT",
    });

    console.log(JSON.stringify(message, null, 2));

    // 确保他们关注我们才能铸造cNFT
    if (isValid && !message.following) {
        return new NextResponse(getFrameHtmlResponse({
            image: {
                src: `${baseURL}/error.jpg`,
                aspectRatio: "1:1",
            },
            buttons: [
                {
                  label: "你需要关注才能铸造!点击重试",
                  action: "post",
                },
            ],
            postUrl: `${baseURL}api/frames`,
        }));
    // 确保他们有已验证的Solana地址
    } else if (isValid && message.interactor.verified_addresses.sol_addresses) {
        const solanaAddresses = message.interactor.verified_addresses.sol_addresses;
        console.log(`SOLANA地址:${solanaAddresses}`);

        if (solanaAddresses.length !== 0) {
            try {
                console.log(`铸造到${solanaAddresses[0]}`);
                // 取第一个地址,以防有多个地址
                const mintResult = await mintCompressedNFT(solanaAddresses[0]!);

                return new NextResponse(getFrameHtmlResponse({
                    image: {
                        src: `${baseURL}/success.jpg`,
                        aspectRatio: "1:1",
                    },
                    buttons: [
                        {
                            label: "成功!在XRAY上查看你的cNFT",
                            action: "link",
                            target: `https://xray.helius.xyz/token/${mintResult.assetId}?network=mainnet`
                        },
                    ],
                }));
            } catch (e: any) {
                console.log(`铸造失败:${e}`);
                return new NextResponse(getFrameHtmlResponse({
                    image: {
                        src: `${baseURL}/error.jpg`,
                        aspectRatio: "1:1",
                    },
                    buttons: [
                        {
                          label: "铸造失败。点击重试",
                          action: "post",
                        },
                    ],
                    postUrl: `${baseURL}api/frames`,
                }));
            }
        } else {
            console.log(`没有找到Solana地址`);
            return new NextResponse(getFrameHtmlResponse({
                image: {
                    src: `${baseURL}/error.jpg`,
                    aspectRatio: "1:1",
                },
                buttons: [
                    {
                      label: "未找到Solana地址。点击重试",
                      action: "post",
                    },
                ],
                postUrl: `${baseURL}api/frames`
            }));
        }
    } else {
        return new NextResponse(getFrameHtmlResponse({
            image: {
                src: `${baseURL}/error.jpg`,
                aspectRatio: "1:1",
            },
            buttons: [
                {
                  label: "无效的frame消息。点击重试",
                  action: "post",
                },
            ],
            postUrl: `${baseURL}api/frames`,
        }));
    }
}

该文件是一个Next.js API路由,处理所有POST请求,用于我们的frame。该文件开始时从next/server导入NextRequestNextResponse,用于处理传入请求和发送响应。我们还从@coinbase/onchainkit/frame导入getFrameMessagegetFrameHtmlResponse,以验证frame消息并为frame交互生成HTML响应。我们还导入了我们之前创建的mintCompressedNFT工具函数。

为了减少代码重复,定义了baseURL。它用于构建资源和API端点的路径。

该文件导出POST函数,该函数解析传入的请求主体以提取frame消息。我们使用getFrameMessage检查传入的frame交互和消息的有效性。我们将请求主体作为JSON传递,并传递默认的Neynar API密钥(即NEYNAR_ONCHAIN_KIT )来完成此操作。Neynar是一个开发平台,旨在简化Farcaster开发。getFrameMessage返回一个Promise,解析为FrameValidationResponse,它被定义为:

export type FrameValidationResponse =
  | { isValid: true; message: FrameValidationData }
  | { isValid: false; message: undefined };

因此,如果frame交互有效,则会返回类型为FrameValidationData的消息,它的定义为:

export interface FrameValidationData {
  button: number; // 被点击按钮的编号
  following: boolean; // 表示查看该frame的用户是否关注cast作者
  input: string; // 用户在frame中输入的文本
  interactor: {
    fid: number; // 查看者的Farcaster ID
    custody_address: string; // 查看者的保管地址
    verified_accounts: string[]; // 查看者的账户地址
    verified_addresses: {
      eth_addresses: string[] | null;
      sol_addresses: string[] | null;
    };
  };
  liked: boolean; // 表示查看该frame的用户是否喜欢该cast
  raw: NeynarFrameValidationInternalModel;
  recasted: boolean; // 表示查看该frame的用户是否转发了该cast
  valid: boolean; // 表示frame是否有效
}

这非常有价值,因为它包含相关数据,例如用户的Farcaster ID,他们是否有任何已验证的Ethereum或Solana地址,以及他们是否喜欢了该cast。在本教程中,我们想检查尝试铸造的用户是否在关注我的资料。如果是,我们将允许他们铸造cNFT。我们还想确保他们有一个已验证的Solana地址,以便我们能够铸造cNFT。

首先,我们检查交互是否有效,以及用户是否关注我的帐户。如果不是,他们会收到验证消息和一个提示他们重试的按钮。然后我们检查用户是否拥有已验证的Solana地址。如果存在一个或多个地址,我们将执行铸造过程。我们取第一个已验证的Solana地址并将其传入mintCompressedNFT。若铸造成功,我们返回成功的图像以及查看cNFT的链接XRAY。在失败时记录错误并以提示用户重试的消息响应。如果未找到已验证的Solana地址,则返回一条错误消息,指示没有已验证的Solana地址,并提示用户重试。最后,如果frame消息无效,我们则返回一条关于无效frame的错误消息,并提示用户重试。

代码使用getFrameHtmlResponse根据铸造过程的特定结果或验证检查生成HTML响应。这包括设置响应的图像、宽高比以及用于特定用户交互的按钮。

推向生产

完成代码后,创建一个新的GitHub存储库并将代码推送到新存储库中。在命令行中执行以下命令以将代码推送到GitHub:

git add .
git commit -m "初始提交"
git remote add origin https://github.com/<username>/<new repo name>.git
git branch -M main
git push -u origin main

在将代码推送到GitHub之后,下一步是部署该应用程序。Vercel提供与GitHub的无缝集成,简化整个部署过程,因此我们将使用它来完成。要继续:

  • 登录到Vercel网站上的帐户。如果你没有帐户,你需要创建一个——他们提供慷慨的Hobby级别(即免费),这对我们的需求足够了。
  • 成功登录后,导航到仪表板并点击新项目按钮。Vercel会提示你从GitHub导入一个项目。选择你在上一步中刚创建的存储库。
  • Vercel将自动检测你使用的框架并建议构建设置。Vercel由Next.js的创建者开发,为我们提供了优质的支持,因此我们无需担心繁琐的配置设置。
  • 配置项目设置后,点击部署按钮。Vercel将自动开始部署过程,构建并将项目部署到一个唯一的Vercel URL。
  • 部署完成后,Vercel会提供你访问实时应用的唯一URL。我的项目托管在https://helius-frame.vercel.app/——GitHub存储库名称后跟.vercel.app。Vercel还支持在项目设置中配置自定义域。

就是这样!通过这些步骤,我们已将Farcaster框架推送到GitHub,并将其托管在Vercel上。你可以使用上述测试工具,如Frames validator来测试框架的功能。剩下的就是使用框架的URL进行发布!

结论

区块链与社交媒体的交集是我们在数字空间内概念和互动方式的重大飞跃。Farcaster和frames的流行转变了过去在传统社交媒体平台上的静态帖子,变为互动体验。本文探讨了Farcaster和frames。提供的教程是介绍如何利用Farcaster最近的Solana支持,锚定cNFT到用户,只需点击一下按钮。无论你是希望在Farcaster上构建的开发者,还是希望以一种新颖有趣的方式浏览他们社交媒体动态的人,可能性都是无穷无尽的。

如果你看到这里,感谢你,匿名人士!如果你希望加入Farcaster,请使用以下邀请链接!请务必在下方输入你的电子邮件地址,以便你能及时了解Solana上的最新动态。准备更深入地了解了吗?今天就来探索Helius博客上的最新文章,继续你的Solana之旅。

附加资源

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

0 条评论

请先 登录 后评论
Helius
Helius
https://www.helius.dev/