WebAssembly-Powered Cloud Computing for On-Chain Data Processing.

The Zephyr Virtual Machine is a WebAssembly Virtual Machine designed to interact with databases and interoperate with Stellar and Soroban, powering cloud custom indexing with Zephyr.
Exploring the ZephyrVM

The Mercury Cloud Execution Environment

The Cloud execution environment allows developers building with Mercury to have the same degree of data access and latency that they would encounter in deploying watcher nodes, but with significantly less costs and no maintenance to bear, and more importantly with a much better developer experience, making building efficient and real-time Web3 APIs much more accessible.

Write small programs, deploy and start getting your data

Building a powerful and fast indexer with custom logic has never been easier. The development process is as simple as writing a smart contract.

No XDR nested matching no more

The Zephyr VM is hardwired to Soroban's environment allowing you to work off-chain with network data with the same ease that you deal with it on-chain.

Fully customizable APIs

Indexing, aggregations, simulations, ledger entry retrievals: all in a single program that runs ledger-by-ledger with access to each ledger transition data in real time. Define your indexed tables the way you want them, export serverless functions and aggregate your responses with your API definition. Or use our graphQL API. The customization is endless.

No vendor lock-in

The Zephyr VM is opensource. This means that our execution environment can be run on any server and power indexing even without relying on Mercury's cloud.

Event catchups

Is your program ingesting and processing Soroban events but you started building with Mercury after the deployment on-chain? No problem, we have built an efficient, parallel service that executes your program against the events of the requested contracts. Run a catchup, wait for it to complete (can even take < 1 min!) and begin querying your data.

Discover what you can build

Build with Zephyr any program that is data-related, apply any kind of logic and deploy it on the cloud

1// slightly stripped down or modified version of the impl for simplicity. Also, pardon the formatting.
2#[derive(DatabaseDerive, Clone)]
3#[with_name("curr_seq")]
4struct Sequence {
5    pub current: u32,
6}
7
8#[no_mangle]
9pub extern "C" fn on_close() {
10    let env = EnvClient::new();
11    let sequence = Sequence {
12        current: env.reader().ledger_sequence()
13    };
14    if let Some(last) = Sequence::read_to_rows(&env).iter().find(|x| {
15        x.current == sequence.current - 1
16    }) {
17        env.update().column_equal_to_xdr("current", &last.current).execute(&sequence);
18    } else {
19        sequence.put(&env)
20    }
21}
22
23

Define your custom ingestion logic as well as your data structures on the database and let us take care of the rest. No need to run any infrastructure

1// slightly stripped down or modified version of the impl for simplicity. Also, pardon the formatting.
2#[derive(Serialize, Deserialize)]
3pub struct ColorMintRequest {
4    source: String,
5    colors: Vec<ColorClient>,
6}
7#[no_mangle]
8pub extern "C" fn simulate_color_mint() {
9    let env = EnvClient::empty();
10    let request: ColorMintRequest = env.read_request_body();
11    let (source, source_addr) = /*source from request*/ ;
12    let function_name = Symbol::new(&env.soroban(), "colors_mine");
13    let mut colors = Map::new(&env.soroban());
14    for color in request.colors {
15        colors.set(color.color, color.amount);
16    }
17    let resp = env.simulate(
18        source, zephyr_sdk::soroban_sdk::xdr::HostFunction::InvokeContract(InvokeContractArgs {
19        contract_address: zephyr_sdk::soroban_sdk::xdr::ScAddress::Contract(Hash(CONTRACT_ADDRESS)),
20        function_name,
21        args: vec![env.to_scval(source_addr), env.to_scval(colors)].try_into().unwrap()})).unwrap();
22    env.conclude(resp)
23}

Write custom RPC functionalities using rust and the native Soroban SDK as typesystem. Define simulation endpoints and getLedegr APIs.

1// Build fully-customizable multi-chart dashboards.
2//
3#[no_mangle]
4pub extern "C" fn dashboard() {
5    let env = EnvClient::empty();
6    let chart = {
7        let supplies = Supply::read_to_rows(&env);
8        let collaterals = Collateral::read_to_rows(&env);
9        let borroweds = Borrowed::read_to_rows(&env);
10        env.log().debug("Aggregating data", None);
11        let aggregated = aggregate_data(supplies, collaterals, borroweds);
12        env.log().debug("Data aggregated", None);
13        let chart = create_chart(&env, aggregated);
14
15        env.log().debug("chart built", None);
16        chart
17    };
18
19    env.conclude(&chart)
20}
21
22
23

Create fully-programmable dashboards to visualize your data in beautiful charts and tables

1// slightly stripped down or modified version of the impl for simplicity. Also, pardon the formatting.
2fn send_message(env: &EnvClient, source: ScVal, amount: ScVal) {
3    // get key from env + build body.
4    env.send_web_request(AgnosticRequest {
5        body: Some(body),
6        url: "https://discordapp.com/api/channels/1234475897092968459/messages".into(),
7        method: zephyr_sdk::Method::Post,
8        headers: vec![("Content-Type".into(), "application/json".into()),
9            ("Authorization".into(), format!("Bot {}", key))]})
10}
11#[no_mangle]
12pub extern "C" fn on_close() {
13    let env = EnvClient::new();
14    let contract_events: Vec<ContractEvent> = env.reader().soroban_events().into_iter()
15        .filter(|event| event.contract_id == Some(Hash(CONTRACT_ADDRESS))).collect();
16    for event in contract_events {
17        if Symbol::new(&env.soroban(), "deposit") == env.from_scval(&event.topics[0])
18          && 10_000_000_000 <= env.from_scval::<i128>(&event.data) {
19            env.log().debug("got deposit larger than 1000 XLM", None);
20            send_message(&env, event.topics[1].clone(), event.data)
21        }
22    }
23}

Build alerts and monitoring systems with access to latest ledger data, and perform web requests directly with the Zephyr program. Create automation flows to power your DaFi strategies

Discover
Leading teams building on Soroban are using Zephyr, Mercury's cloud environmen. Learn why.

Why Mercury's Cloud Environment.

Real-Time, Fast, Reliable, and Cost-Efficient

Mercury's cloud execution environment and subscriptions enable for fast, reliable and cost-efficient data access.

All In One

Mercury is the final stop for developers working on Soroban: RPC (custom simulation, entry retrieval), and indexing solutions. All in a single place.

On The Cloud

Everything runs on the cloud as "serverless functions", just type mercury-cli deploy and your program is running.

Best Developer Experience

Soroban is hardwired to the Zephyr VM (literally), allowing you to work within the same native environment and types you're writing contracts in and providing the most accessible way of working with data off-chain across the whole industry.

Resources and Help

Documentation & Examples

Learn how to write Zephyr programs to build your application's API with Mercury.

Need Help? Ask us on Discord

Our team is very active on the xyclooLabs discord channel, just post a question in the help channel and you'll here from us!

Examples repository

Access the expanding examples repository with the most common Zephyr use cases to start building in no time.