Price Feeds Tutorial
Example Code: The complete working example for this tutorial is available at sb-on-demand-examples/sui/feeds/basic
This tutorial walks you through integrating Switchboard oracle price feeds into your Sui Move contracts using the Quote Verifier pattern. You'll learn how to securely fetch, verify, and use real-time price data.
What You'll Build
A Move contract that:
Fetches real-time price data from multiple Switchboard oracles
Verifies oracle signatures cryptographically
Validates data freshness and price deviation
Stores verified prices for your DeFi logic
Plus a TypeScript client that fetches oracle data and submits it to your contract.
Prerequisites
Sui CLI installed (Installation Guide)
Node.js 18+ and npm/pnpm
A Sui keypair with SUI tokens (testnet or mainnet)
Basic understanding of Move and TypeScript
Key Concepts
The Quote Verifier Pattern
Switchboard uses a Quote Verifier pattern to ensure oracle data is legitimate. The verifier:
Checks that data comes from authorized oracles on the correct queue
Tracks timestamps and slots to prevent replay attacks
Enables custom validation logic (freshness, deviation limits)
Why Use Quote Verifier?
Without verification:
Anyone could submit fake prices if you don't check the queue ID
You'd have to track last update timestamps yourself
Stale data could be replayed to manipulate prices
With verification:
Only data from the authorized oracle queue is accepted
Automatic freshness checks prevent stale data
Replay attacks are prevented
You don't need to manually track update timestamps
Feed Hashes
Each price feed has a unique 32-byte hex identifier. You can find feed hashes in the Switchboard Explorer.
Example: BTC/USD feed hash:
The Move Contract
Here's the complete Move contract that consumes oracle data with built-in verification:
Contract Walkthrough
Imports
QuoteVerifier- Manages quote verification and storageQuotes- The signed oracle data structureDecimal- Switchboard's decimal type for price values
QuoteConsumer Struct
The QuoteConsumer is a shared object that stores:
quote_verifier: Handles signature verification and prevents replay attackslast_price: Most recent verified pricelast_update_time: Timestamp for freshness checksmax_age_ms: Maximum acceptable quote age (e.g., 300000 = 5 minutes)max_deviation_bps: Maximum price change in basis points (e.g., 1000 = 10%)
The update_price Function
This is the core function that processes oracle data:
verify_quotes()- Verifies all oracle signatures and ensures they're from the correct queuequote_exists()- Confirms the requested feed is in the quotesget_quote()- Retrieves the verified quote dataFreshness check - Rejects data older than 10 seconds
Deviation check - Prevents sudden price jumps that might indicate manipulation
Store and emit - Updates state and emits a
PriceUpdatedevent
Business Logic Examples
The contract includes example functions for common DeFi use cases:
The TypeScript Client
Here's the complete TypeScript client that creates a QuoteConsumer and updates prices:
Client Walkthrough
Step 1: Create QuoteConsumer
This creates a shared QuoteConsumer object tied to Switchboard's oracle queue.
Step 2: Fetch Oracle Quotes
Quote.fetchUpdateQuote() contacts Crossbar to get signed price data from multiple oracles. The quotes object is added to the transaction automatically.
Step 3: Update Price
This calls your contract's update_price function with the fetched quotes. The Move contract will verify signatures and update the stored price.
Project Structure
Available Scripts
Running the Example
1. Clone the Examples Repository
2. Install Dependencies
3. Build the Move Contract
4. Deploy the Contract
Save the package ID from the deployment output.
5. Run the Example
Expected Output
Adding to Your Project
1. Add Switchboard to Move.toml
2. Import in Your Move Module
3. Add Quote Verifier to Your Struct
4. TypeScript Dependencies
Available Feeds
BTC/USD
0x4cd1cad962425681af07b9254b7d804de3ca3446fbfd1371bb258d2c75059812
ETH/USD
0xa0950ee5ee117b2e2c30f154a69e17bfb489a7610c508dc5f67eb2a14616d8ea
SOL/USD
0x822512ee9add93518eca1c105a38422841a76c590db079eebb283deb2c14caa9
SUI/USD
0x7ceef94f404e660925ea4b33353ff303effaf901f224bdee50df3a714c1299e9
Find more feeds at the Switchboard Explorer.
Deployments
Mainnet
0xa81086572822d67a1559942f23481de9a60c7709c08defafbb1ca8dffc44e210
Testnet
0x28005599a66e977bff26aeb1905a02cda5272fd45bb16a5a9eb38e8659658cff
Troubleshooting
"EInvalidQuote"
The requested feed hash is not in the quotes
Verify the feed hash is correct and included in
fetchUpdateQuote()
"EQuoteExpired"
Quote data is older than 10 seconds
Fetch fresh data before calling
update_price()Check network latency
"EPriceDeviationTooHigh"
Price changed more than the configured
max_deviation_bpsThis can happen during high volatility
Adjust the threshold if needed for your use case
"EInvalidQueue"
The quotes are from a different oracle queue
Verify you're using the correct queue ID for your network (mainnet vs testnet)
Build Errors
Next Steps
Multiple Feeds: Pass multiple feed hashes to
fetchUpdateQuote()to update several prices in one transactionReal-time Streaming: See the Surge Price Stream tutorial for WebSocket-based streaming
Custom Feeds: Learn how to create custom data feeds in the Custom Feeds section
Last updated