本文介绍了如何使用 Gelato 的 Web3 Functions 结合 OpenAI 生成 NFT。
博客 — 用例
AI 遇见 Web3
在过去的几个月里,我们已经看到了 OpenAI 能力的一个小而令人难以置信的缩影,如果你是一名 web3 开发者,你可能会问自己,集成 web3 和 OpenAI 的一个好的例子是什么。
在 web3 生态系统中,主要有两个用例:DeFi 和 NFTs。最终,DeFi 都是关于价格变动、交易、期权、衍生品等,在这种情况下,OpenAI 预测价格变动的能力尚未得到证实。
因此,我们将专注于第二个用例:NFTs。NFTs 是资产数字财产的注册表。NFT 集合使用随机性来创建 NFT 的特征和属性,确定性地创建与 NFT 关联的图像。
图像生成和随机性是 OpenAI 的核心,那么我们如何将这两个世界结合起来呢?请记住,NFT 在链上铸造,而 OpenAI 图像在链下生成,连接这两个世界的唯一可能的方法是使用 Gelato 的 Web3 函数 或类似的服务,该服务提供链上和链下资源之间的通信。
Web3 函数的目标是为开发者提供一种 web3 原生的替代方案,以在 AWS 或 Google Cloud 等中心化平台上运行服务器端逻辑。使用 Web3 函数,开发者可以使用强大、可扩展和信任最小化的基础设施来增强他们的智能合约,该基础设施可以为他们所有的链下服务器组件提供动力——而不会牺牲去中心化!
Web3 函数每分钟运行一次,可以检查链上的条件并调用任何链下 API。如果满足某些条件,Gelato Web3 函数将向预定义的合约发送交易。
在我们的用例中,我们不仅要铸造 NFT,我们还希望每个 NFT 图像都由 OpenAI 生成,并且图像是即时生成的。如果没有 Gelato Web3 函数的强大功能,这项任务似乎是不可能完成的任务。值得庆幸的是,有了 Web3 函数,实际上非常简单:
用户铸造 NFT,Gelato Web3 函数每分钟检查一次新 NFT 的铸造位置。如果铸造了新的 NFT,Gelato Web3 函数将调用 OpenAI API,下载图像,将其存储在 IPFS 上,并更新合约上的 NFT 元数据。
我们将使用标准的 NFT ERC-721 合约,我们允许任何人铸造一个 NFT,并且我们将创建一个由 Gelato Web3 函数触发的附加方法,当 OpenAI 生成并且元数据可用时。
function mint(bool _isNight) external whenNotPaused {
require(!hasMinted[msg.sender], "Already minted!");
tokenIds.increment();
uint256 newItemId = tokenIds.current();
_mint(msg.sender, newItemId);
_setTokenURI(newItemId, notRevealedUri);
hasMinted[msg.sender] = true;
tokenIdByUser[msg.sender] = newItemId;
nightTimeByToken[newItemId] = _isNight;
emit MintEvent(newItemId);
}
function revealNft(uint256 tokenId, string memory tokenURI) external onlyGelatoMsgSender {
_setTokenURI(tokenId, tokenURI);
emit MetadataUpdate(tokenId);
}
我们可以在 mint 方法中看到它期望一个布尔值 _isNight。这是因为我们允许用户选择他们是否希望 NFT 的背景是夜晚还是白天!
值得注意的是,revealNft 具有修饰符 only on GelatoMsgSender。此修饰符确保只有 Gelato 创建的代理才能执行此方法。
Gelato Web3 函数的示意代码遵循以下模式:
Web3Function.onRun(async (context: Web3FunctionContext) => {
const { userArgs, storage, secrets, provider } = context;
/// If conditions aren't met
return { canExec: false
Message:’no execution due…’}
// if conditions are met
return { canExec: true
callData: payload to be executed}
})
让我们看看实现的每个代码块。
////// User Arguments
const nftAddress = userArgs.nftAddress;
if (!nftAddress) throw new Error("Missing userArgs.nftAddress please provide");
////// User Secrets
const nftStorageApiKey = await secrets.get("NFT_STORAGE_API_KEY");
if (!nftStorageApiKey) throw new Error("Missing secrets.NFT_STORAGE_API_KEY");
const openAiApiKey = await secrets.get("OPEN_AI_API_KEY");
if (!openAiApiKey) throw new Error("Missing secrets.OPEN_AI_API_KEY");
////// User Storage
const lastProcessedId = parseInt((await storage.get("lastProcessedId")) ?? "0");
首先,我们需要从用户参数中获取 nftContract 地址。
其次,我们将从我们的密钥中获取 nftStorageApiKey,以将 OpenAI 生成的图像上传到 IPFS,并且我们还需要 openAIKey 来调用 OpenAI API。 最后,我们将从我们的存储中获取上次处理的 tokenID,因此我们可以确保只有新的 NFT 才能获得新图像。
const nft = new Contract(nftAddress as string, NFT_ABI, provider);
const currentTokenId = await nft.tokenIds();
if (currentTokenId.eq(BigNumber.from(lastProcessedId))) {
return { canExec: false, message: "No New Tokens" };
}
const tokenId = lastProcessedId + 1;
在使用 ethes.js 实例化 NFT 合约后,我们应该检查已铸造的 NFT 的当前数量。如果此数字等于上次处理的 NFT,我们可以返回到我们的任务而不执行任何交易。
但是,如果有新的 NFT,那么我们将继续生成下一个 NFT 图像。
这部分很简单:我们实例化一个客户端 OpenAI,我们创建提示,然后我们获取图像 URL。
//// Generating Attribures
function generateNftProperties(isNight: boolean) {
const timeSelected = isNight ? "at night" : "at sunset";
const description = `A cute robot eating an icecream with Dubai background ${timeSelected} in a cyberpunk art, 3D, video game, and pastel salmon colors`;
return {
description,
attributes: [\
{ trait_type: "Time", value: timeSelected },\
{ trait_type: "Place", value: "Eth Dubai" },\
{ trait_type: "Eating", value: "Gelato" },\
{ trait_type: "Powered", value: "Web 3 Functions" },\
],
};
}
const openai = new OpenAIApi(new Configuration({ apiKey: openAiApiKey }));
let imageUrl: string;
try {
const response = await openai.createImage({
prompt: nftProps.description,
size: "512x512",
});
imageUrl = response.data.data[0].url as string;
console.log(`Open AI generated image: ${imageUrl}`);
一旦我们有了图像 URL,我们就会将图像下载为 Blob,实例化 nftStorage 客户端,将图像上传到 IPFS,并返回元数据。
// Publish NFT metadata on IPFS
const imageBlob = (await axios.get(imageUrl, { responseType: "blob" })).data;
const client = new NFTStorage({ token: nftStorageApiKey });
const imageFile = new File([imageBlob], `gelato_bot_${tokenId}.png`, { type: "image/png" });
const metadata = await client.store({
name: `Eth Dubai GelatoBot #${tokenId}`,
description: nftProps.description,
image: imageFile,
attributes: nftProps.attributes,
collection: { name: "EthDubai-GelatoBots", family: "ethdubai-gelatobots" },
});
console.log("IPFS Metadata:", metadata.url);
await storage.set("lastProcessedId", tokenId.toString());
最后,我们将编码我们的交易以显示 NFT 并在链上发送
return {
canExec: true,
callData: nft.interface.encodeFunctionData("revealNft", [tokenId, metadata.url]),};
你可以在这里看到完整的代码
Gelato 是一个 Web3 云平台,使开发者能够创建自动化的、无 Gas 的和链下感知的 Layer 2 链和智能合约。400 多个 web3 项目多年来一直依赖 Gelato 来促进 DeFi、NFT 和游戏领域的数百万笔交易。
Gelato RaaS: 一键部署你自己的定制 ZK 或 OP L2 链,内置原生账户抽象和所有 Gelato 中间件。
Web3 函数: 通过运行去中心化的云函数,将你的智能合约连接到链下数据和计算。
自动化: 通过以可靠、开发者友好和去中心化的方式自动执行交易来自动化你的智能合约。
中继: 通过易于使用的 API,让你的用户可以访问可靠、强大且可扩展的无 Gas 交易。
账户抽象 SDK: Gelato 与 Safe 合作,构建了一个完整的账户抽象 SDK,结合了 Gelato 行业最佳的无 Gas 交易能力和行业最安全的智能合约钱包。
订阅我们的新闻通讯并打开你的 Twitter 通知,以获取有关 Gelato 生态系统的最新更新! 如果你有兴趣成为 Gelato 团队的一员并构建互联网的未来,请浏览空缺职位并在此处申请 here。
- 原文链接: gelato.cloud/blog/chatgp...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!