This guide covers the setup and use of Switchboard data feeds within your project, using the Aggregator module for updating feeds and integrating Switchboard in Move.
Typescript-SDK Installation
To use Switchboard On-Demand, add the following dependencies to your project:
NPM
npm install @switchboard-xyz/aptos-sdk --save
Bun
bun add @switchboard-xyz/aptos-sdk
PNPM
pnpm add @switchboard-xyz/aptos-sdk
Adding Switchboard to Move Code
To integrate Switchboard with Move, add the following dependencies to Move.toml:
In the example.move module, use the Aggregator and CurrentResult types to access the latest feed data.
module example::switchboard_example {use aptos_framework::aptos_coin::AptosCoin;use aptos_framework::object::{Self, Object};use switchboard::aggregator::{Self, Aggregator, CurrentResult};use switchboard::decimal::Decimal;use switchboard::update_action; public entry fun my_function(account:&signer, update_data: vector<vector<u8>>) {// Update the feed with the provided data update_action::run<AptosCoin>(account, update_data);/** * You can use the following code to remove and run switchboard updates from the update_data vector, * keeping only non-switchboard byte vectors: * * update_action::extract_and_run<AptosCoin>(account, &mut update_data); */// Get the feed objectlet aggregator: address =@0xSomeFeedAddress;let aggregator:Object<Aggregator> = object::address_to_object<Aggregator>(aggregator);// Get the latest update info for the feedlet current_result:CurrentResult= aggregator::current_result(aggregator);// Access various result propertieslet result:Decimal= aggregator::result(¤t_result); // Update resultlet (result_u128, result_neg) = decimal::unpack(result); // Unpack resultlet timestamp_seconds = aggregator::timestamp(¤t_result); // Timestamp in seconds// Other properties you can use from the current resultlet min_timestamp:u64= aggregator::min_timestamp(¤t_result); // Oldest valid timestamp usedlet max_timestamp:u64= aggregator::max_timestamp(¤t_result); // Latest valid timestamp usedlet range:Decimal= aggregator::range(¤t_result); // Range of resultslet mean:Decimal= aggregator::mean(¤t_result); // Average (mean)let stdev:Decimal= aggregator::stdev(¤t_result); // Standard deviation// Use the computed result as needed... }}
Once dependencies are configured, updated aggregators can be referenced easily.
This implementation allows you to read and utilize Switchboard data feeds within Move. If you have any questions or need further assistance, please contact the Switchboard team.
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 in Typescript [optional]
import { CrossbarClient, SwitchboardClient, Aggregator, ON_DEMAND_MAINNET_QUEUE_KEY, ON_DEMAND_TESTNET_QUEUE_KEY,} from"@switchboard-xyz/aptos-sdk";// get the aptos clientconstconfig=newAptosConfig({ network:Network.MAINNET,// network a necessary param / if not passed in, full node url is required});constaptos=newAptos(config);// create a SwitchboardClient using the aptos clientconstclient=newSwitchboardClient(aptos);// for initial testing and development, you can use the public// https://crossbar.switchboard.xyz instance of crossbarconstcrossbar=newCrossbarClient("https://crossbar.switchboard.xyz");// ... define some jobs ...constqueue= isMainnet?ON_DEMAND_MAINNET_QUEUE_KEY:ON_DEMAND_TESTNET_QUEUE_KEY;// Store some job definitionconst { feedHash } =awaitcrossbarClient.store(queue, jobs);// try creating a feedconstfeedName="BTC/USDT";// Require only one oracle response neededconstminSampleSize=1;// Allow update data to be up to 60 seconds oldconstmaxStalenessSeconds=60;// If jobs diverge more than 1%, don't allow the feed to produce a valid updateconstmaxVariance=1e9;// Require only 1 job responseconstminJobResponses=1;//==========================================================// Feed Initialization On-Chain//==========================================================// ... get the account object for your signer with relevant key / address ...// get the signer addressconstsignerAddress=account.accountAddress.toString();constaggregatorInitTx=awaitAggregator.initTx(client, signerAddress, { name: feedName, minSampleSize, maxStalenessSeconds, maxVariance, feedHash, minResponses,});constres=awaitaptos.signAndSubmitTransaction({ signer: account, transaction: aggregatorInitTx,});constresult=awaitaptos.waitForTransaction({ transactionHash:res.hash, options: { timeoutSecs:30, checkSuccess:true, },});// Log the transaction resultsconsole.log(result);
Updating Feeds
All you have to do in order to use Switchboard On-Demand updates is pass the data string along with your transaction and call the update prior to reading. In this example we pass the updates into the ${exampleAddress}::switchboard_example::my_functionfunction. Alternatively, feeds can be cranked off-chain for fresh updates.
constaggregator=newAggregator(sb, aggregatorId);// Fetch and log the oracle responsesconst { updates } =awaitaggregator.fetchUpdate(signerAddress);// Create a transaction to run the feed updateconstupdateTx=awaitswitchboardClient.aptos.transaction.build.simple({ sender: singerAddress, data: { function:`${exampleAddress}::switchboard_example::my_function`, functionArguments: [updates], },});// Sign and submit the transactionconstres=awaitaptos.signAndSubmitTransaction({ signer: account, transaction: updateTx,});// Wait for the transaction to completeconstresult=awaitaptos.waitForTransaction({ transactionHash:res.hash, options: { timeoutSecs:30, checkSuccess:true, },});// Log the transaction resultsconsole.log(result);