Skip to content

switchboard-xyz/starknet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Switchboard On-Demand on Starknet

Switchboard is a multi-chain, permissionless oracle protocol allowing developers to fully control how data is relayed on-chain to their smart contracts.

Documentation: docs.switchboard.xyz

Active Deployments

The Switchboard On-Demand service is currently deployed on the following networks:

Check out the example contract to see how to create a price feed using Switchboard On-Demand.

Typescript-SDK Installation

To use Switchboard On-Demand, add the following dependencies to your project:

NPM

npm install @switchboard-xyz/starknet-sdk --save

Bun

bun add @switchboard-xyz/starknet-sdk

PNPM

pnpm add @switchboard-xyz/starknet-sdk

Creating an Aggregator and Sending Transactions

Building a feed in Switchboard can be done using the Typescript SDK, or it can be done with the Switchboard Web App. Visit our docs for more on designing and creating feeds.

Building Feeds

import {
  SwitchboardClient,
  Aggregator,
  STARKNET_TESTNET_QUEUE,
  STARKNET_MAINNET_QUEUE,
} from "@switchboard-xyz/starknet-sdk";

export async function create_feed() {
  // .. initialize wallet or starknet account ..
  const client = new SwitchboardClient(wallet_account);

  const params = {
    authority: wallet_account.address,
    name: "EXAMPLE/USD",
    queueId: STARKNET_TESTNET_QUEUE, // or STARKNET_MAINNET_QUEUE
    toleratedDelta: 100,
    maxStaleness: 100,
    feedHash,
    maxVariance: 5e9,
    minResponses: 1,
    minSamples: 1, // required to be 1 for Starknet
  };

  const aggregator = await Aggregator.init(client, params);

  console.log("Feed created!", await aggregator.loadData());

  return aggregator;
}

create_feed();

Adding Switchboard to Cairo Code

To integrate Switchboard with your cairo code, first add the following dependencies to Scarb.toml:

switchboard = { git = "https://github.com/switchboard-xyz/starknet.git" }

Example Cairo Code for Using Switchboard Values

In the module, use the latest result function to read the latest data for a feed.

#[starknet::interface]
pub trait IBtcFeedContract<T> {
    fn update(
        ref self: T, update_data: ByteArray
    );
}

#[starknet::contract]
mod example_contract {
    use core::{ByteArray, panic_with_felt252};
    use starknet::{ContractAddress, get_block_timestamp};

    // @dev Import the Switchboard dispatcher and the Switchboard dispatcher trait.
    use switchboard::{ISwitchboardDispatcher, ISwitchboardDispatcherTrait};

    // Storage for the Switchboard contract addresss, the BTC Feed ID, and the BTC price.
    #[storage]
    struct Storage {
        switchboard_address: ContractAddress, // <--- Switchboard contract address
        btc_feed_id: felt252, // <--- Feed ID
        btc_price: i128,
    }

    // Constructor to initialize the contract storage.
    #[constructor]
    fn constructor(
        ref self: ContractState,
        switchboard_address: ContractAddress, >
        btc_feed_id: felt252
    ) {
        self.switchboard_address.write(switchboard_address);
        self.btc_feed_id.write(btc_feed_id);
    }

    #[abi(embed_v0)]
    impl BtcFeedContract of super::IBtcFeedContract<ContractState> {
        fn update(
            ref self: ContractState,
            update_data: ByteArray // <--- Update data to be passed to the Switchboard contract
        ) {
            let switchboard = ISwitchboardDispatcher { contract_address: self.switchboard_address.read() };

            // Update the price feed data
            switchboard.update_feed_data(update_data);

            // Read the fresh price feed
            let btc_price = switchboard.latest_result(self.btc_feed_id.read());

            // Check the age of the update - if it is older than 60 seconds, panic
            if (btc_price.max_timestamp < get_block_timestamp() - 60) {
                panic_with_felt252('Price feed is too old');
            }

            // write the price to storage
            self.btc_price.write(btc_price.result);
        }
    }
}

Executing updates in TypeScript

To get the update data for a feed, use the following code:

import {
  ProviderInterface,
  AccountInterface,
  Contract,
  RpcProvider,
  Account,
  constants,
  CallData,
} from "starknet";
import { ABI } from "./abi"; // <-- Import the ABI for the contract
import { readFileSync } from "fs";
import { SwitchboardClient, Aggregator } from "@switchboard-xyz/starknet-sdk";

function trimHexPrefix(hex: string) {
  return hex.startsWith("0x") ? hex.slice(2) : hex;
}

async function main() {
  // .. initialize wallet / starknet account ..

  const exampleAddress = process.env.EXAMPLE_ADDRESS;
  if (!exampleAddress) {
    throw new Error("EXAMPLE_ADDRESS not set");
  }

  const feedId = process.env.FEED_ID;
  if (!feedId) {
    throw new Error("FEED_ID not set");
  }

  // get the contract
  const contract = await getBtcFeedContract(exampleAddress, account);

  // get the aggregator
  const aggregator = new Aggregator(
    new SwitchboardClient(account),
    trimHexPrefix(feedId)
  );

  // Fetch the update ByteArray and oracle responses
  const { updates, responses } = await aggregator.fetchUpdate();

  // Run the update
  const tx = await contract.update(CallData.compile(updates));
  console.log("Transaction hash:", tx.transaction_hash);
  await account.waitForTransaction(tx.transaction_hash);
}

main().catch((e) => {
  console.error(e);
  process.exit(1);
});

This implementation allows you to read and utilize Switchboard data feeds within Cairo. If you have any questions or need further assistance, please contact the Switchboard team.

DISCLAIMER: ORACLE CODE AND CORE LOGIC ARE AUDITED - THE AUDIT FOR THIS ON-CHAIN ADAPTER IS PENDING

About

Starknet On-Demand Integration and SDKs

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published