Published on

Mercury Community Indexes and Dashboards: Powering Next-Gen Network Data Charting and Collaboration.

Authors

At xyclooLabs we're building Mercury to be the go-to data platform for Stellar developers and a widely-requested feature from blockchain data platforms is custom indexes, generally protocol-focused, and the ability to create and access dashboards.

While Mercury already supported external indexes reads and an alpha charting feature for creating dashboards, it was only for dashboards and indexes built by the xyclooLabs team and without robust backend functionalities to allow for discoverability and creation of said indexes and dashbaords.

Today we announce the new indexes and dashboards functionality, that includes updates on:

  • the zephyr-sdk, including the more intuitive and higher-level DashboardBuilder.
  • the backend infrastrucure allowing for the creation, linking, indexing and discoverability of indexes and dashboards.
  • the mercury webapp which now includes a community-dedicated section to exploring and accessing indexes and dashboards.

Community Indexes

Community indexes at their core are publicly accessible tables that are registered as and index through the zephyr.toml extension specification.

Indexes can be used by other Mercury programs in their ingestion, data retrieval, or to create new dashboards.

For example, the below program accesses Blend's all-time borrowed index to plot a chart for ClickPesa's blend pool:

use std::collections::HashMap;
use zephyr_sdk::{charting::DashboardBuilder, prelude::*, DatabaseDerive, EnvClient};

#[derive(DatabaseDerive, Clone)]
#[with_name("borrowed")]
#[external("2")]
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,
}

#[no_mangle]
pub extern "C" fn dashboard() {
    let env = EnvClient::empty();
    let clickpesa_all_time_borrowed: Vec<Borrowed> = env
        .read_filter()
        .column_equal_to(
            "pool",
            "CARYQKYQ6HBDWRDO65X4H4KTBMH46R7QXB5DLN3Q57IM5IFDVIFEG2LM".to_string(),
        )
        .read()
        .unwrap();
    // ...
}

Accessing the index is done by following the creator-provided instructions (table name + creator id).

Community Dashboard

If your program externs a dashboard function that you want to make discoverable within the community dashboards you can also publish them through the zephyr.toml extension specification.

Additionally, composing dashboards can now also be done more easily with the DashboardBuilder:

let mut dashboard = DashboardBuilder::new(
    "ClickPesa Borrow Dashboard",
    "Explore the borrows and repays happening on the clickpesa blend pool",
);

let mut aggregated: HashMap<String, Vec<(String, i64)>> = HashMap::new();
for entry in clickpesa_all_time_borrowed {
    aggregated
        .entry(entry.asset)
        .or_insert(vec![])
        .push((entry.ledger.to_string(), entry.borrowed as i64));
}

for (asset, data) in aggregated {
    let asset = format!("{}...{}", &asset[0..5], &asset[27..32]);
    let ledgers = data.iter().map(|pair| pair.clone().0).collect();
    let supply = data.iter().map(|pair| pair.clone().1).collect();

    dashboard = dashboard.add_line_chart(
        &format!("{} borrowed evolution", asset),
        ledgers,
        vec![(&asset, supply)],
    )
}

env.conclude(dashboard.build())

For Builders

Are you building on Soroban and have your protocol already on testnet or mainnet which you'd like to get listed in the community dashboards? Reach us out on Discord or at [email protected], and we'll get you started!