Mercury Documentation
  • Get Started with Mercury
    • Pricing
    • Endpoints
    • Authentication
  • The Definitive Guide to Understanding The Mercury's Stack Vision
  • Retroshades
    • Introduction to Retroshades
    • Get Started
      • Importing the Retroshades SDK
      • Writing and Emitting Retroshades
      • Deploying to Mercury Retroshades
      • Querying Retroshades
  • Zephyr: Full Customization
    • Introduction
    • General concepts
      • Zephyr Programs
      • Accessing the Ledger: Contract Entries
      • Accessing the Ledger Meta: Contract Events
      • Database Interactions
      • Create Custom Callable APIs: Serverless Functions
      • Catchups
      • Using Soroban inside Zephyr
    • Quickstart
    • Learn
      • Introduction to Mercury's Cloud and the Zephyr Stack
      • Get Started: Set Up and Manage the Project
        • Create the Project
        • Writing the Program
        • Local Testing
        • Deploy
        • Data catchups/backfill
        • Monitor Execution
        • Querying
      • Database Interactions
        • Zephyr.toml: Define the Tables Structure
        • Understanding Database Interactions
        • Database Operations
      • Accessing the Ledger
      • Accessing Ledger Transition: Soroban Events
      • Working with Contract Custom Types
      • Working with Soroban SDK Types
      • Web Requests, Automation and Alerts.
      • Zephyr.toml Extensions: Indexes And Dashboard
      • Reading From Indexes/External Tables
      • Custom APIs - Serverless Functions
        • General Concepts
        • Custom RPC-alike Endpoints
        • Querying APIs for Composable Data
      • Data Catchups/Backfill
      • Custom Dashboards
        • Creating the Dashboard
        • Plotting: Simple
        • Complex Plotting
    • Support
  • Mercury "Classic"
    • Subscriptions
      • API Definition
    • Queries
      • Contract Events
      • Contract Data Entry Updates
      • Stellar Operations, Balances, and Account Objects
  • TUTORIALS
    • Zephyr
      • Self-hosting Zephyr
      • No-RPC Dapp
      • Indexing a DeFi liquidity pool (Blend)
      • Building a Secure DeFi Real-Time Bot Through Smart Accounts
      • Monitoring Large Deposits with Zephyr and Sending Web Alerts
    • Mercury Classic
      • Index and query contract events
Powered by GitBook
On this page
  • Understanding Indexes
  • Accessing a public Index
  1. Zephyr: Full Customization
  2. Learn

Reading From Indexes/External Tables

Learn how Zephyr programs can access publicly indexed data.

PreviousZephyr.toml Extensions: Indexes And DashboardNextCustom APIs - Serverless Functions

Last updated 7 months ago

Understanding Indexes

Zephyr tables are by default shareable across programs.

Note that when pricing kicks off creators of certain tables will be able to manage how their tables are accessed with custom rules.

This functionality allows any program or Custom Dashboards to access already indexed + live-updated data on Mercury. As seen in , creators can share their tables with the community and significantly simplify the work for othr users. All the needed data to access an already existing public table can be found in the section of the app.

By selecting the desired index, it's possible to copy the table struct to paste in the program that needs to access it.

Accessing a public Index

Let's make things practical and jump straight to an example. This code returns all indexed Blend Mainnet borrowed operations for a given pool:

use serde::{Deserialize, Serialize};
use zephyr_sdk::{prelude::*, EnvClient, DatabaseDerive};

// importing the public table
#[derive(DatabaseDerive, Clone)]
#[with_name("borrowed")]
#[external("35")]    // notice that! Below you have the full explanation
pub struct Borrowed {
    pub id: i64,
    pub timestamp: u64,
    pub ledger: u32,
    pub pool: String,
    pub asset: String,
    pub borrowed: i128,
    pub delta: i128,
    pub source: String,
}

#[derive(Deserialize)]
pub struct Request {
    pool: String,
}

#[derive(Serialize)]
pub struct ResponseObject {
    pub timestamp: u64,
    pub ledger: u32,
    pub asset: String,
    pub borrowed: String,
    pub delta: String,
    pub source: String,
}

#[no_mangle]
pub extern "C" fn get_borrowed_by_pool() {
    let env = EnvClient::empty();
    let request: Request = env.read_request_body();
    // starting from the publicly indexed "borrowed" table we filter through the Borrowed objects
    // for the ones whose ".pool" field matches our request body. 
    let borrowed: Vec<Borrowed> = env.read_filter().column_equal_to("pool", request.pool).read().unwrap();
    // return those as a Vec of objects of type "ResponseObject"
    let borrowed: Vec<ResponseObject> = borrowed.iter().map(|obj| {
        ResponseObject {
            timestamp: obj.timestamp,
            ledger: obj.ledger,
            asset: obj.asset.clone(),
            borrowed: (obj.borrowed as i64).to_string(),
            delta: (obj.delta as i64).to_string(),
            source: obj.source.clone()
        }
    }).collect();

    env.conclude(&borrowed)
}

The key here is the attribute

#[external("35")]

Which tells the compiler (and then the ZephyrVM) that you're reading from the borrowed table created by id 35 (in this case, blend's Mainnet deployment).

This function can be easily called through:

curl -X POST https://mainnet.mercurydata.app/zephyr/execute -H "Authorization: Bearer $MERCURY_JWT" -H 'Content-Type: application/json' -d '{"project_name":"zephyr-hello-world", "mode":{"Function": {"fname": "get_borrowed_by_pool", "arguments": "{\"pool\":\"CDVQVKOY2YSXS2IC7KN6MNASSHPAO7UN2UR2ON4OI2SKMFJNVAMDX6DP\"}"}}}'

The result will be a list of all the borrows for a certain pool, each borrow displaying the specified fields.

As you can see here, we are accessing some data that we have not indexed ourselves quite easily, and this can be done from every point of your Zephyr program.

Zephyr.toml Extentions
Community Indexes