使用 Gelato Web3 函数将智能合约连接到 Web2 API

  • gelato
  • 发布于 2023-08-05 22:59
  • 阅读 36

本文介绍了Gelato Web3 Functions,它提供了一个强大的解决方案,用于将链上智能合约与链下数据连接起来。文章通过五个实际案例展示了如何使用Gelato Web3 Functions将Web2 API与智能合约集成,包括更新预言机智能合约、自动化交易、体育博彩平台、自动化内容生成和NFT创建等。

Gabriel - Gelato Ambassador

Gabriel - Gelato Ambassador

·

使用 Gelato Web3 Functions 将智能合约连接到 Web2 API

Gelato Web3 Functions 提供了一个强大的解决方案,用于将链上智能合约与链下数据连接起来。链上组件由你想要使用链下数据(API / subgraph等)自动化的智能合约组成,而链下元素是访问 Web2 API 并处理数据的 Web3 Function。

通过配置 Web3 Function Task,你可以无缝地集成两者,从而为去中心化应用程序实现更大的控制和自动化。让我们来探索如何创建和利用 Web3 Functions 来提高 Dapp 的效率和功能。在这篇博文中,我们将演示 5 种将 web2 API 与智能合约集成的方法,并提供代码示例以便于实际理解。

使用 CoinGecko Price API 更新 Oracle 智能合约

Coingecko 是一个专门从事资产索引的平台,允许用户跟踪数千种加密货币和代币的价格。除了提供实时的价格信息外,Coingecko 还提供有关市值、交易量、历史价格趋势等数据。

得益于 Web3 Functions,可以从 Coingecko 实时获取特定资产的当前价格。以我们的例子,我们想要知道以太坊(ETH)的当前价格,你可以使用 Web3 Function 查询 Coingecko 的 API 并检索更新后的价格。

一旦你获得了所需的价格,你就可以在链上使用它来更新智能合约,根据价格触发自动操作,甚至可以基于此外部数据创建复杂的金融机制。

实现

第一步是编写一个脚本,其中包含从 Web3Function 实例返回执行调用数据的逻辑。此 web3 function 定期使用从 CoinGecko 的价格 API 检索的信息来更新 Oracle 智能合约。

代码链接

import { Web3Function, Web3FunctionContext } from "@gelatonetwork/web3-functions-sdk";
import { Contract, ethers } from "ethers";
import ky from "ky"; // we recommend using ky as axios doesn't support fetch by default

const ORACLE_ABI = [\
  "function lastUpdated() external view returns(uint256)",\
  "function updatePrice(uint256)",\
];

Web3Function.onRun(async (context: Web3FunctionContext) => {
  const { userArgs, gelatoArgs, multiChainProvider } = context;
  const provider = multiChainProvider.default();

  // Retrieve Last oracle update time
  // 检索上次 oracle 更新时间
  const oracleAddress = "0x71b9b0f6c999cbbb0fef9c92b80d54e4973214da";
  const oracle = new Contract(oracleAddress, ORACLE_ABI, provider);
  const lastUpdated = parseInt(await oracle.lastUpdated());
  console.log(`Last oracle update: ${lastUpdated}`);

  // Check if it's ready for a new update
  // 检查是否已准备好进行新的更新
  const nextUpdateTime = lastUpdated + 300; // 5 min
  const timestamp = (await provider.getBlock("latest")).timestamp;
  console.log(`Next oracle update: ${nextUpdateTime}`);
  if (timestamp < nextUpdateTime) {
    return { canExec: false, message: `Time not elapsed` };
  }

  // Get current price on coingecko
  // 获取 coingecko 上的当前价格
  const currency = "ethereum";
  const priceData: any = await ky
    .get(
      `https://api.coingecko.com/api/v3/simple/price?ids=${currency}&vs_currencies=usd`,
      { timeout: 5_000, retry: 0 }
    )
    .json();
  price = Math.floor(priceData[currency].usd);
  console.log(`Updating price: ${price}`);

  // Return execution call data
  // 返回执行调用数据
  return {
    canExec: true,
    callData: [{\
      to: oracleAddress,\
      data: oracle.interface.encodeFunctionData("updatePrice", [price])\
  }],
  };
});

使用 Web3 Functions 自动交易

自动交易使交易者能够实施复杂的策略,而无需持续监控市场。Gelato Web3 Functions 在此过程中充当强大的工具,允许根据特定条件执行智能合约。我们正在使用 Uniswap SDK 来监控价格。

我们将重点关注两种交易策略:

  1. 追踪止损:此策略将在价格上涨时自动上推止损,从而提供免受下行风险的保护。当达到止损时,将退出交易,从而确保在波动的市场中具有一定程度的安全性。

  2. 反弹入场:使用此方法,如果价格开始向上移动超过指定阈值,并且我们尚未进行交易,我们将进入交易。这利用了市场动能,并且可能是参与趋势资产的有效方式。

实现

智能合约 - Solidity 智能合约“MockSwap”执行 USDC 和 WETH 之间的“虚假”交换。它允许用户设置operators,存入资金,并在 USDC 和 WETH 之间执行买入或卖出交换。

Web3 Functions

  1. 追踪止损策略

此策略将在价格上涨时自动上推止损,从而提供免受下行风险的保护。当达到止损时,将退出交易,从而确保在波动的市场中具有一定程度的安全性。

以下是在代码中实现追踪止损的方式:

  • 如果正在交易中,并且价格正在上涨,它会将最高价格(lastMax)更新为当前价格。
  • 如果价格没有变化,它什么也不做。
  • 如果价格下跌但小于退出阈值,它什么也不做。
  • 如果价格下跌大于退出阈值,它将通过调用带有卖出参数的交换函数来退出交易。

代码链接

if (activeTrade) {

    /////  ==== We are IN TRADE ===================== /////
    ///// ==== 我们正在交易中 ===================== /////
    ///  *****************************************************  ///
    if (lastMax == 0) {
      await storage.set("lastMax", price.toString());
      return { canExec: false, message: "Initiatig Price Exit" };
    }

    let diff = lastMax - price;
    if (diff < 0) {
      ///  *****************************************************  ///
      ///  Price is going up, update to new max
      ///  价格正在上涨,更新为新的最大值
      ///  *****************************************************  ///
      await storage.set("lastMax", price.toString());
      console.log(
        `Old lastMax: ${lastMax.toString()}, New lastMax: ${price.toString()}`
      );
      return { canExec: false, message: "No Trade Exit ---> Price UP " };
    } else if (diff == 0) {
      ///  *****************************************************  ///
      ///  Price not moving doing Nothing
      ///  价格没有变动,什么都不做
      ///  *****************************************************  ///
      return {
        canExec: false,
        message: `No Trade Exit ---> No Price change: ${price.toString()} `,
      };
    } else if (diff / lastMax < EXIT / 100) {
      ///  *****************************************************  ///
      ///  Price decrease too small, doing Nothing
      ///  价格下跌太小,什么都不做
      ///  *****************************************************  ///
      console.log(
        `Current lastMax: ${lastMax.toString()}, currentPrice: ${price.toString()}`
      );
      return {
        canExec: false,
        message: `No Trade Exit ---> Price decrease Small ${(
          (diff / lastMax) *
          100
        ).toFixed(2)} %`,
      };
    } else {
      ///  *****************************************************  ///
      ///  Price Decrease Greater than threshold ---> EXIT THE TRADE
      ///  价格跌幅大于阈值 ---> 退出交易
      ///  *****************************************************  ///
      await storage.set("lastMin", price.toString());

      console.log(
        `Trade Exit---> Price Decrease ${((diff / lastMax) * 100).toFixed(
          2
        )} greater than ${EXIT} %`
      );

      const payload = await returnCalldata(price,mockSwapContract,user,false)
      return  payload;
    }
  }
  1. 反弹入场策略

使用反弹入场方法,如果价格开始向上移动超过指定阈值,并且我们尚未进行交易,我们将进入交易。这利用了市场动能。

以下是在代码中实现反弹入场的方式:

  • 如果没有进行交易并且价格正在下跌,它会将最低价格(lastMin)更新为当前价格。
  • 如果价格没有变化,它什么也不做。
  • 如果价格上涨但小于入场阈值,它什么也不做。
  • 如果价格上涨大于入场阈值,它将通过调用带有买入参数的交换函数来进入交易。
else {

    /////  ==== We are NOT in a trade ===================== /////
    ///// ==== 我们没有进行交易 ===================== /////
    ///  *****************************************************  ///
    if (lastMin == 0) {
      await storage.set("lastMin", price.toString());
      console.log("Initiatig Price Entry")

      // do initial transacrion
      // 进行初始交易
      const payload = await returnCalldata(price,mockSwapContract,user,true)
      return  payload;
    }

    let diff = price - lastMin;

    if (diff < 0) {
      ///  *****************************************************  ///
      ///  Price is going down, update to new min
      ///  价格正在下跌,更新为新的最小值
      ///  *****************************************************  ///
      console.log(
        `Old lastMin: ${lastMin.toString()}, New lastMin: ${price.toString()}`
      );
      await storage.set("lastMin", price.toString());
      return { canExec: false, message: "No Trade Entry ---> Price Down " };
    } else if (diff == 0) {
      ///  *****************************************************  ///
      ///  Price not moving doing Nothing
      ///  价格没有变动,什么都不做
      ///  *****************************************************  ///
      return {
        canExec: false,
        message: `No Trade Entry ---> No Price change: ${price.toString()} `,
      };
    } else if (diff / lastMin < ENTRY / 100) {
      ///  *****************************************************  ///
      ///  Price Increate too small, doing Nothing
      ///  价格上涨太小,什么都不做
      ///  *****************************************************  ///
      console.log(
        `Current lastMin: ${lastMin.toString()}, currentPrice: ${price.toString()}`
      );
      return {
        canExec: false,
        message: `No Trade Entry ---> Price Increase too small ${(
          (diff / lastMin) *
          100
        ).toFixed(2)} %`,
      };
    } else {
      ///  *****************************************************  ///
      ///  Price Increate Greater than threshold ---> Enter a TRADE
      ///  价格上涨大于阈值 ---> 进入交易
      ///  *****************************************************  ///

      await storage.set("lastMax", price.toString());

      const payload = await returnCalldata(price,mockSwapContract,user,true)

      return  payload;
    }
  }
});

体育博彩平台

在构建体育博彩平台时,假设你有一个促进博彩过程的智能合约。用户可以对各种体育赛事下注,智能合约会持有资金,直到结果确定。但是,智能合约本身无法直接访问真实世界的数据,例如体育比赛的结果。这就是 Web3 Functions 发挥作用的地方。

实现

要确定获胜的赌注并触发支付过程,你需要使用 Web3 Functions 将你的平台连接到提供实时体育数据的外部 API。

这些 API 将提供体育赛事的结果,并且基于该数据,Web3 Function 将在区块链上执行交易。这些交易将处理将资金分配给下获胜赌注的用户。

一旦体育赛事结束,Web3 Function 会从 API 获取相关数据,对其进行处理,并与智能合约交互以启动支付过程。这种自动化确保了获胜的博彩者无需任何中心化机构或人工干预即可获得奖励。

Web3Function.onRun(async (context: Web3FunctionContext) => {
  // Call SportsDB API to get game status & score
  // 调用 SportsDB API 以获取游戏状态和分数
  const gameId = (context.userArgs.gameId as string) ?? "Argentina_vs_France";
  let gameEvent;
  try {
    const api = `https://www.thesportsdb.com/api/v1/json/3/searchevents.php?e=${gameId}`;
    const res = await axios.get(api);
    gameEvent = res.data.event[0];
  } catch (err) {
    return { canExec: false, message: `SportDb API call failed` };
  }

  // Wait for match to be finished
  // 等待比赛结束
  console.log("Game details:", gameEvent);
  if (gameEvent.strStatus !== "Match Finished") {
    return { canExec: false, message: `Match not finished yet` };
  }

// Prepare the CallData to be executed
// 准备要执行的 CallData
  const BETTING_CONTRACT_ABI = ["function updateGameScore(string, uint16, uint16)"];
  const bettingInterface = new utils.Interface(BETTING_CONTRACT_ABI);

// Pushing the callData to the callData Array
// 将 callData 推送到 callData 数组
  const callData = []
  callData.push({
    to: targetContract,
    data:bettingInterface.encodeFunctionData("updateGameScore",[\
      gameId,\
      parseInt(gameEvent.intHomeScore),\
      parseInt(gameEvent.intAwayScore),\
       ])
})
// Publish final score on-chain
// 在链上发布最终得分

  return {
    canExec: true,
    callData: callData
    };
 });

使用 ChatGPT 在 Lens 上自动创建内容

人工智能和 web3 的结合有潜力解决人工智能领域中现有的挑战,同时还在 web3 中释放众多的创新机会。

Gelato 的 Web3 Functions 使智能合约能够利用 AI 的强大功能,方法是将智能合约连接到 OpenAI ChatGPT API,以根据给定的提示生成创意内容。在我们的应用程序中,Gelato 的 Web3 Functions 帮助我们将链下 Open AI API 连接起来以生成创意内容,并对其进行自动化以每 8 小时在 Lens 上安排一次。

实现

我们有 LensGelatoGPT 智能合约,该合约处理使用 AI 自动创建内容的提示管理。

然后,Gelato 的 Web3 Functions 代码调用 OpenAI API 以生成创意内容,该内容由从 LensGPT 智能合约获得的提示指导。在此之后,使用 LensClient 获取并验证 Lens 发布元数据。验证后,内容将封装在元数据中,并使用 Web3Storage API 上载到 IPFS。

最后,创建 postData 对象,然后将其编码为 LensHub 合约的“post”函数的调用数据,然后发布到 Lens Protocol 上。

整个过程的最终结果是你的内容出现在 Lenster 上,Lenster 是使用 Lens Protocol 构建的社交媒体 Web 应用程序。

代码链接

生成 AI 文本响应和元数据验证

    const openai = new OpenAIApi(
       new Configuration({ apiKey: SECRETS_OPEN_AI_API_KEY })
     );
     const response = await openai.createCompletion({
       model: "text-davinci-003",
       prompt: ` ${contentURI} in less than 15 words.`,
      …
     });
     let text = response.data.choices[0].text as string;

  /// Build and validate Publication Metadata
  /// 构建和验证发布元数据
       const uuid = uuidv4();
       const pub = {

         content: text,
       ... more code
       };

       // Checking Metadata is Correct
       // 检查元数据是否正确
       ... code here

       // Upload metadata to IPFS
       // 将元数据上传到 IPFS
       const storage = new Web3Storage({ token: WEB3_STORAGE_API_KEY! });
       const myFile = new File([JSON.stringify(pub)], "publication.json");
       const cid = await storage.put([myFile]);
       contentURI = `https://${cid}.ipfs.w3s.link/publication.json`;

       console.log(`Publication IPFS: ${contentURI}`);

准备区块链交易数据

const postData = {
 profileId: prompt.profileId,
 contentURI,
 collectModule: collectModuleAddress,
 referenceModule: "0x0000000000000000000000000000000000000000",
 referenceModuleInitData: "0x",
};

const iface = new utils.Interface(lensHubAbi);

callDatas.push({
 to: lensHubAddress,
 data: iface.encodeFunctionData("post", [postData]),
});

使用 Stable Diffusion API 创建 NFT

在此用例中,AI 和区块链协同工作以创建独特的 NFT 体验。Gelato 的 Web3 Functions 连接到 StabilityAI 的 Stable Diffusion 工具,以从给定的提示生成 NFT 图像。然后,这些图像用作 NFT 的一部分,从而将区块链的链上世界与 AI 的链下世界联系起来。该过程简化了视觉上吸引人的 NFT 的创建,使其更易于访问并增强了整体用户体验。

实现

GelatoNft 智能合约:你将学习如何使用此智能合约铸造新的 NFT,直到最终揭示它们为止,都将保持一种悬念感。

Stable Diffusion:此来自 StabilityAI 的 AI 工具生成独特的图像,这些图像将成为你 NFT 的元数据。你将探索如何将 AI 驱动的图像集成到你的 NFT 中。

Gelato 的 Web3 Functions:这些功能充当你的 NFT 智能合约与链下的 Stable Diffusion API 之间的通道,从而自动将 AI 创建的图像分配给你的 NFT。在本教程结束时,你将掌握如何使用 Gelato 的 Web3 Functions 来简化你的 NFT 创建过程。

代码链接

识别要处理的未公开 NFT

此代码识别要处理的未公开非同质化代币(NFT)。它检查智能合约中尚未公开的 NFT,并将它们添加到批处理中以进行处理。诸如时间之类的属性在内部用于自定义 NFT 的属性,例如指定所描绘的场景是在晚上还是在日落时进行设置。

// Retreive current state
// 检索当前状态
const nft = new Contract(nftAddress as string, NFT_ABI, provider);
const lastProcessedId = parseInt(
(await storage.get("lastProcessedId")) ?? "0"
);
const currentTokenId = (await nft.tokenIds()).toNumber();
console.log("currentTokenId", currentTokenId);
if (currentTokenId === lastProcessedId) {
return { canExec: false, message: "No New Tokens" };
}

// Get batch of next token ids to process in parallel
// 获取要并行处理的下一个代币 ID 批次
const tokenIds: number[] = [];
let tokenId = lastProcessedId;
let nbRpcCalls = 0;
const MAX_RPC_CALLS = 30;
const MAX_NFT_IN_BATCH = 5;
while (
tokenId < currentTokenId &&
tokenIds.length < MAX_NFT_IN_BATCH &&
nbRpcCalls < MAX_RPC_CALLS
) {
// Check if token needs to be revealed or is already revealed
// 检查是否需要公开代币或是否已公开
tokenId++;
const tokenURI = await nft.tokenURI(tokenId);
if (tokenURI === NOT_REVEALED_URI) {
    tokenIds.push(tokenId);
} else {
    console.log(`#${tokenId} already revealed!`);
}
nbRpcCalls++;
}

if (tokenIds.length === 0) {
console.log(`All NFTs already revealed!`);
await storage.set("lastProcessedId", tokenId.toString());
return { canExec: false, message: "All NFTs already revealed" };
}

console.log("NFTs to reveal:", tokenIds);
const tokensData = await Promise.all(
tokenIds.map(async (tokenId) => {
    // Generate NFT properties
    // 生成 NFT 属性
    const isNight = await nft.nightTimeByToken(tokenId);
    const nftProps = generateNftProperties(isNight);
    console.log(
      `#${tokenId} Stable Diffusion prompt: ${nftProps.description}`
    );

使用 Stable Diffusion 生成 NFT 图像,在 IPFS 上发布元数据并更新智能合约

// Generate NFT image with Stable Diffusion
// 使用 Stable Diffusion 生成 NFT 图像
let imageUrl: string;
try {
const stableDiffusionResponse = await fetch(
    "https://stablediffusionapi.com/api/v3/text2img",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        key: stableDiffusionApiKey,
        prompt: nftProps.description,
        // other parameters...
        // 其他参数...
      }),
    }
);
const stableDiffusionData = await stableDiffusionResponse.json();
imageUrl = stableDiffusionData.output[0] as string;
} catch (_err) {
// error handling
// 错误处理
}

// Publish NFT metadata on IPFS
// 在 IPFS 上发布 NFT 元数据
const imageBlob = (await axios.get(imageUrl, { responseType: "blob" })).data;
const nftStorage = new NFTStorage({ token: nftStorageApiKey });
const imageFile = new File([imageBlob], `gelato_nft_${tokenId}.png`, {
type: "image/png",
});
const metadata = await nftStorage.store({
// metadata details...
// 元数据详细信息...
});
console.log(`#${tokenId} IPFS Metadata ${metadata.url}`);

// Updating the smart contract
// 更新智能合约
callDatas.push({
to: nft.address,
data: nft.interface.encodeFunctionData("revealNft", [\
    token.id,\
    token.url,\
]),
});

关于 Gelato

Discord 上加入我们的社区和开发者讨论。

Web3 Functions 现已在 private beta 中提供。有关更多信息,请查看 Web3 Functions 文档。要了解如何编写、测试和部署你自己的 Web3 Functions,请查看我们的 深入教程

在此处申请 here 成为首批测试 Web3 Functions 的人之一。

如果你是第一次阅读有关我们的信息

Gelato 是 web3 的去中心化后端,它使构建者能够创建增强的智能合约,这些合约在所有主要的 EVM 兼容区块链(包括 Ethereum、Arbitrum、Polygon、Optimism、zkSync 等等)上实现自动化、gasless 和链下感知。400 多个 web3 项目多年来一直依赖 Gelato 来支持 DeFi、NFT 和游戏领域数百万笔交易的执行。 Gelato 目前提供四项服务:

  • Web3 Functions: 通过运行去中心化云函数,将你的智能合约连接到链下数据和计算。

  • Automate: 通过以可靠、对开发者友好且去中心化的方式自动执行交易来自动化你的智能合约

  • Relay: 通过易于使用的 API 让你的用户可以访问可靠、强大且可扩展的 gasless 交易

  • Gasless Wallet: 一个强大的 SDK,使开发人员能够通过结合 Gelato Relay + Safe's Smart Contract Wallet 来提供世界一流的 UX,从而实现账户抽象

见证由 Gelato 领导的迈向去中心化未来的持续旅程!

订阅我们的新闻通讯并打开你的 Twitter 通知,以获取有关 Gelato 生态系统的最新更新!

如果你有兴趣成为 Gelato 团队的一员并构建互联网的未来,请浏览空缺职位并在此处申请 here

Gabriel - Gelato Ambassador

Gabriel - Gelato Ambassador

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

0 条评论

请先 登录 后评论
gelato
gelato
The Web3 Developer Cloud. Launch your own chain via our #1 Rollup-As-A-Service platform.