Skip to main content

Introduction

Molpha is a decentralized oracle network that provides reliable and secure data feeds for various assets. This guide will walk you through the process of integrating with Molpha oracles on the Solana blockchain, allowing your programs to access real-time data.

Key Concepts

The Molpha oracle program is built around a few key accounts:

The Feed Account

The Feed account is the primary account you will interact with. It stores all the information about a specific data feed, including:
  • name_hash: A unique identifier for the feed.
  • authority: The public key of the account that can manage the feed.
  • latest_answer: The most recent data point published to the feed.
  • answer_history: A circular buffer containing the history of recent answers.
  • subscription_due_time: The timestamp when the feed subscription expires.
The structure of the Feed account is defined as follows:
#[account]
pub struct Feed {
    pub name_hash: [u8; 32],
    pub authority: Pubkey,
    pub feed_type: FeedType,
    pub job_id: [u8; 32],
    pub data_source: Pubkey,
    pub min_signatures_threshold: u8,
    pub frequency: u64,
    pub ipfs_cid: String,
    pub latest_answer: Answer,
    pub answer_history: Vec<Answer>,
    pub history_idx: u64,
    pub subscription_due_time: i64,
    pub price_per_second_scaled: u64,
    pub created_at: i64,
    pub bump: u8,
}

The Answer Struct

The Answer struct contains the actual data value and the timestamp when it was recorded.
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Copy, Default)]
pub struct Answer {
    pub value: [u8; 32],
    pub timestamp: i64,
}
The value is a 32-byte array, which can represent different data types depending on the feed. For example, for a price feed, it could be a scaled integer.

On-chain Integration

To use Molpha oracle data in your Solana program, you need to:
  1. Pass the Feed account to your instruction.
  2. Deserialize the account data.
  3. Access the latest_answer to get the current value.
Here’s an example of a simple program that retrieves the latest price from a Molpha price feed.

1. Define the Instruction Context

First, define the accounts required for your instruction. You’ll need the Feed account from the Molpha oracle program.
use anchor_lang::prelude::*;
use molpha::state::Feed; // Assuming 'molpha' is the crate name of the oracle program

#[derive(Accounts)]
pub struct ReadPrice<'info> {
    #[account(
        // Add any constraints you need, e.g., checking the feed authority
    )]
    pub molpha_feed: Account<'info, Feed>,
}

2. Implement the Instruction Logic

In your instruction logic, you can access the deserialized molpha_feed account and read its latest_answer.
pub fn read_price(ctx: Context<ReadPrice>) -> Result<()> {
    let feed = &ctx.accounts.molpha_feed;

    // Access the latest answer
    let latest_answer = feed.latest_answer;
    let price_value = latest_answer.value;
    let timestamp = latest_answer.timestamp;

    msg!("Latest price: {:?}", price_value);
    msg!("Timestamp: {}", timestamp);

    // Your program logic here...

    Ok(())
}

3. Full Example

Here is a complete example of a Solana program that reads from a Molpha oracle.
use anchor_lang::prelude::*;
use molpha::state::Feed;

declare_id!("YourProgramId111111111111111111111111111111");

#[program]
pub mod my_dapp {
    use super::*;

    pub fn read_price(ctx: Context<ReadPrice>) -> Result<()> {
        let feed = &ctx.accounts.molpha_feed;

        // Access the latest answer
        let latest_answer = feed.latest_answer;
        let price_value = latest_answer.value;
        let timestamp = latest_answer.timestamp;

        msg!("Latest price: {:?}", price_value);
        msg!("Timestamp: {}", timestamp);

        // Check if the feed is active
        let current_timestamp = Clock::get()?.unix_timestamp;
        if !feed.is_subscription_active(current_timestamp) {
            // Handle inactive feed
            msg!("Feed subscription is not active!");
            // You might want to return an error here
        }

        // Your program logic here...

        Ok(())
    }
}

#[derive(Accounts)]
pub struct ReadPrice<'info> {
    #[account()]
    pub molpha_feed: Account<'info, Feed>,
}

Off-chain Usage with TypeScript

You can also fetch and use Molpha oracle data from off-chain applications using TypeScript.
import { Connection, PublicKey } from '@solana/web3.js';
import { Program, AnchorProvider } from '@coral-xyz/anchor';
import { IDL as MolphaIdl, Molpha } from './molpha_idl'; // Replace with actual IDL path

async function getOraclePrice() {
    const connection = new Connection('https://api.devnet.solana.com');
    const provider = new AnchorProvider(connection, {} as any, {}); // Use a proper wallet provider
    
    const molphaProgramId = new PublicKey('moLfNsTqLqej38QPHu4xq7uMBVK14MRQCQWhBhz8X3k');
    const program = new Program<Molpha>(MolphaIdl, molphaProgramId, provider);
    
    const feedAddress = new PublicKey('...'); // Replace with the actual feed address
    
    const feedAccount = await program.account.feed.fetch(feedAddress);
    
    const latestAnswer = feedAccount.latestAnswer;
    const price = latestAnswer.value; // This will be a byte array
    const timestamp = latestAnswer.timestamp;

    console.log('Latest Answer:', latestAnswer);
    console.log('Price:', price);
    console.log('Timestamp:', timestamp.toString());
}

getOraclePrice();

Next Steps

Resources