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
  • Advantages of building your API
  • Building your custom API
  • Resources
  1. Zephyr: Full Customization
  2. Learn
  3. Custom APIs - Serverless Functions

Querying APIs for Composable Data

Create fully custom callable APIs with access to stored and ledger data.

PreviousCustom RPC-alike EndpointsNextData Catchups/Backfill

Last updated 8 months ago

To query data from Zephyr there are two options: using the standardized GrapQl API, or setting up a querying endpoint through a sererless function. The second option is what will be covered in this chapter and has the following advantages.

Advantages of building your API

We already talked about these advantages , now let's be more specific:

  • Full customization: you can configure your endpoint to accept and return data in your preferred format, and aggregate it within the function as needed.

  • Combine table and ledger queries within the same query/execution: for example, query an address from a table and use it as a parameter to retrieve a ledger entry.

  • This level of flexibility allows for minimizing the amount of data stored in the database, along with costs. You only need to save key data in your tables, which can then be used to retrieve additional required information from the current state of the ledger as needed.

  • Lastly, as previously discussed, working with Zephyr enables you to directly parse table, event, and ledger data within the program using Rust and the Soroban type system. This approach allows you to format the return data as desired, thereby reducing the workload on the caller.

Building your custom API

The setup remains consistent: create a serverless function and handle a request. Within the function, you have the freedom to combine various functions learned so far to create a custom API that will return some specific data. Retrieve ledger/table data, aggregate and modify it, and return the result in your desired format. Here’s a simple example of how you can create an API that composes data previously stored in tables and ledger data:

#[no_mangle]
pub extern "C" fn get_signers_by_address() {
    let env = EnvClient::empty();
    let request: Request = env.read_request_body();
    let borrower: Borrower = env.read_filter().column_equal_to("borrowers", request.borrower).read().unwrap();
    let res: i128 = env.read_contract_entry_by_key([0;32], DataKey::Balance(env.from_scval(&borrower.address))).unwrap().unwrap();

    env.conclude(&res)
}

As you can see, there's no limit to what can be done with Zephyr. This was just a simple demonstration of how a more complex data aggregation can be done to create an API with Zephyr, but for a more complex example, you can take a look at Blend's indexing program.


Resources

In the request body, we have a borrower field of type Borrower (which of course, as seen , needs to be imported into the program). With the read:filter() function, we're accessing our tables, and more specifically the "borrowers" columns, where a list of Borrower objects is stored. We're taking just the borrower that matches our request.

For the sake of simplicity we are omitting some repetitive passages, but make sure to have defined the Request type in your program beforehand (look at for reference). Then, by using the borrower.address field of the object we just found, we read from the ledger the Balance entry for that address for a certain contract and return it.

here
https://blog.xycloo.com/blog/indexing-blend-ybx-pool
before
General Concepts