Real-Time Data Automation with Custom Oracles

Gelato Team

Jul 26, 2023

TL;DR

The integration of Pyth and Gelato's Web3 Functions enables the creation of finely-tuned, customized oracles, enhancing the automation and accuracy of on-chain price updates. Pyth provides real-time financial data, while Web3 Functions connect smart contracts to off-chain data and computation.

In this article, we explore how Pyth uses Gelato Web3 Functions to create automated oracles that push prices on-chain every hour or whenever the price changes by 2% or more. This ensures blockchain data remains fresh and reliable.


Pyth Network

Pyth is a specialized oracle network providing precise, real-time financial data to smart contracts. It aggregates prices from over 80 first-party publishers including major exchanges and market makers. With multiple updates per second, Pyth delivers robust and accurate data feeds across asset classes such as crypto, equities, and commodities.


Web3 Functions

Web3 Functions are the decentralized equivalent of AWS Lambda or Google Cloud functions. They allow developers to execute on-chain transactions based on arbitrary off-chain data. Combined with Pyth, Web3 Functions let developers create custom oracles that fetch data and push updates on-chain with predefined logic.


Integration

We showcase two demos:


  • W3F to Consumer Contract (updates a dedicated oracle contract)

  • W3F to Pyth (updates Pyth network contracts directly)

W3F to Consumer Contract

This Web3 Function fetches the latest price data from Pyth and updates the smartOracle contract only if:

  • Price changes by 2% or more since the last update, or

  • 24 hours have elapsed since the last update

Data Initialization

Web3Function.onRun(async (context: Web3FunctionContext) => {
  const { userArgs, storage } = context;
  const lastPrice = JSON.parse(
    (await storage.get("lastPrice")) ?? "{}"
  ) as IPRICE;

  const smartOracle = userArgs.SmartOracle as string;
  const priceIds = userArgs.priceIds as string[];

Fetching Price Data

const connection = new EvmPriceServiceConnection("https://xc-testnet.pyth.network");
const check = (await connection.getLatestPriceFeeds(priceIds)) as any[];

Initialization on First Run

if (lastPrice.price == undefined) {
  await storage.set("lastPrice", JSON.stringify(currentPrice));
  const updatePriceData = await connection.getPriceFeedsUpdateData(priceIds);
  const callData = iface.encodeFunctionData("updatePrice", [updatePriceData]);
  return { canExec: true, callData: [{ to: smartOracle, data: callData }] };
}

Price Update Logic

const dayInSec = 24 * 60 * 60;
const diff = Math.abs(lastPrice.price - currentPrice.price) / lastPrice.price;

if (diff >= 0.02 || currentPrice.timestamp - lastPrice.timestamp > dayInSec) {
  const updatePriceData = await connection.getPriceFeedsUpdateData(priceIds);
  const callData = iface.encodeFunctionData("updatePrice", [updatePriceData]);
  await storage.set("lastPrice", JSON.stringify(currentPrice));
  return { canExec: true, callData: [{ to: smartOracle, data: callData }] };
} else {
  return { canExec: false, message: "No conditions met" };
}

W3F to Pyth

This Web3 Function fetches price data from the Pyth network and updates the Pyth contract directly. The logic is similar: it triggers updates if the price changes by 2% or more or if 24 hours have passed since the last update.


const connection = new EvmPriceServiceConnection("https://xc-testnet.pyth.network");
const check = (await connection.getLatestPriceFeeds(priceIds)) as any[];

if (!check.length || !check[0].price?.price) {
  return { canExec: false, message: "No price available" };
}

const currentPrice: IPRICE = {
  price: +check[0].price.price,
  timestamp: +check[0].price.publishTime,
};

const diff = Math.abs(lastPrice.price - currentPrice.price) / lastPrice.price;
if (diff >= 0.02 || currentPrice.timestamp - lastPrice.timestamp > dayInSec) {
  const updatePriceData = await connection.getPriceFeedsUpdateData(priceIds);
  const callData = pythnetwork.interface.encodeFunctionData(
    "updatePriceFeeds",
    [updatePriceData]
  );
  const fee = (await pythnetwork.getUpdateFee(updatePriceData)).toString();
  await storage.set("lastPrice", JSON.stringify(currentPrice));
  return { canExec: true, callData: [{ to: pythNetworkAddress, data: callData, value: fee }] };
} else {
  return { canExec: false, message: "No conditions met" };
}

Conclusion

Gelato Web3 Functions combined with Pyth enables developers to build custom, automated, and reliable oracle solutions. These integrations ensure timely updates and trustworthy on-chain data, paving the way for more advanced decentralized applications.


About Gelato

Gelato powers over 400 Web3 projects, enabling millions of transactions across DeFi, NFTs, and gaming. Its decentralized backend services include:


  • Web3 Functions: Connect smart contracts to off-chain data & computation.

  • Automate: Automate smart contracts with decentralized, reliable execution.

  • Relay: Provide gasless transactions through a simple API.

  • Gasless Wallet: SDK combining Gelato Relay with Safe’s smart contract wallet for account abstraction.

Witness Gelato’s journey towards a decentralized future. Subscribe to our newsletter and follow Twitter for updates.

Ready to build?

Start with a testnet, launch your mainnet in days, and scale with industry-leading UX.

Ready to build?

Start with a testnet, launch your mainnet in days, and scale with industry-leading UX.

Ready to build?

Start with a testnet, launch your mainnet in days, and scale with industry-leading UX.

Ready to build?

Start with a testnet, launch your mainnet in days, and scale with industry-leading UX.