Skip to main content

How to use real-time data in TON contracts

RedStone is a pull oracle that uses an alternative design for providing oracle data to smart contracts. Instead of constantly persisting data on the contract’s storage, the information is brought on-chain only when needed by end users. Until that moment, data remains in the decentralized cache layer, powered by RedStone light cache gateways and a stream-based data broadcasting protocol. Data is transferred to the contract by end users, who attach signed data packages to their function invocations. The information integrity is verified on-chain through signature checking.

Install the RedStone SDK

Install the RedStone TON connector and other necessary dependencies:
npm install @redstone-finance/ton-connector @redstone-finance/sdk

Write code to interact with oracle

Off-chain data fetch and update

The following code snippet demonstrates how to fetch price updates and interact with RedStone contracts on TON:
import { TonPricesContractConnector } from "@redstone-finance/ton-connector";
import { ContractParamsProvider, getSignersForDataServiceId } from "@redstone-finance/sdk";

async function main() {
  // Configure API endpoint
  const apiV2Config = {
    apiEndpoint: "https://testnet.toncenter.com/api/v2/jsonRPC",
    apiKey: "your-api-key-here", // Get your TON Center API key
  };

  // Initialize the connector
  const contractAddress = "EQCMxfukwpP3BI_6Pn3lmOXgxlp3dPabVGOM0UvJCjsDhkdD";
  const prices = new TonPricesContractConnector(network, contractAddress);

  // Configure RedStone data service parameters
  const paramsProvider = new ContractParamsProvider({
    dataServiceId: "redstone-main-demo",
    uniqueSignersCount: 1,
    dataPackagesIds: ["ETH", "BTC"],
    authorizedSigners: getSignersForDataServiceId("redstone-main-demo"),
  });

  // Get prices using on-the-fly processing (doesn't modify contract state)
  const pricesFromPayload = await (await prices.getAdapter()).getPricesFromPayload(paramsProvider);
  console.log("ETH and BTC prices from payload:", pricesFromPayload);

  // Write prices to contract storage (modifies contract state)
  await (await prices.getAdapter()).writePricesFromPayloadToContract(paramsProvider);
  console.log("Prices written to contract storage successfully.");

  // Read prices from contract storage
  const storedPrices = await (await prices.getAdapter()).readPricesFromContract(paramsProvider);
  console.log("Stored prices:", storedPrices);

  // Get timestamp of last update
  const lastUpdateTimestamp = await (await prices.getAdapter()).readTimestampFromContract();
  console.log("Last update timestamp:", lastUpdateTimestamp);
}

main().catch(console.error);
This code snippet does the following:
  1. Imports the TonPricesContractConnector and sets up the RedStone SDK.
  2. Configures the API endpoint and creates a connector to your deployed contract.
  3. Sets up a ContractParamsProvider with the data service ID and feed identifiers.
  4. Fetches price data using on-the-fly processing (no gas cost).
  5. Writes price data to the contract’s storage (requires gas).
  6. Reads stored prices and the last update timestamp from the contract.

Contract types

RedStone provides several contract types for different use cases:

Price Manager

Manages multiple price feeds with signature verification and supports both on-the-fly processing and storage persistence.

Single Feed Manager

Simplified version for handling a single price feed, reducing gas costs for single-feed applications.

Price Feed

An individual feed contract that stores price data for a specific asset.

Sample Consumer

Example consumer contract that demonstrates how to read data from price feeds.

Error handling

Common error codes you might encounter:
  • 300+: Insufficient valid signers (less than signer_count_threshold)
  • 200+: Timestamp validation failed (data too old or in the future)
  • Other codes: See RedStone constants

Additional resources

You may find these additional resources helpful for developing your TON application: