Resource filtering pattern

Heimdahl uses a consistent pattern-based filtering approach across all data types, with specific actions for accessing historical data and subscribing to real-time updates. This document explains our filtering pattern syntax, how to use it effectively, and why we chose this approach over alternative filtering methods.

Pattern Structure

Heimdahl provides a consistent pattern structure across interfaces, with slight naming differences between command line and REST API and SDKs.

Command Line Interface

{resource} {action} {pattern}

Where:

  • {resource} is the primary data category (event, transfer, swap) - singular form

  • {action} is either list (for historical data) or subscribe (for real-time updates)

  • {pattern} is a structured filtering expression using dot notation

REST API Interface

/{resources_plural}/{action}/{pattern}

Where:

  • {resources_plural} is the primary data category in plural form (events, transfers, swaps) to follow RESTful conventions

  • {action} is either list (for historical data) or subscribe (for real-time updates)

  • {pattern} is the same structured filtering expression as used in the command line

Actions

Heimdahl provides two primary actions for each resource type:

  • list: Retrieves historical data matching the specified pattern

  • subscribe: Creates a real-time subscription for new data matching the pattern

Pattern Syntax By Resource Type

Each resource type has a specific pattern format that reflects its unique properties:

Event Pattern

event list {chain}.{network}.{token_address}.{event_name}
event subscribe {chain}.{network}.{token_address}.{event_name}

Examples:

event list base.mainnet.0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913.Transfer
event subscribe base.mainnet.0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913.Transfer

The first query returns historical Transfer events, while the second creates a real-time subscription.

Transfer Pattern

transfer list {chain}.{network}.{symbol}.{sender_addr}.{receiver_addr}.{size}
transfer subscribe {chain}.{network}.{symbol}.{sender_addr}.{receiver_addr}.{size}

Examples:

transfer list base.mainnet.usdc.all.all.all
transfer subscribe base.mainnet.usdc.all.all.all

The first query returns historical USDC transfers, while the second subscribes to new transfers as they occur.

Swap Pattern

swap list {chain}.{network}.{symbol1}.{symbol2}.{size}
swap subscribe {chain}.{network}.{symbol1}.{symbol2}.{size}

Examples:

swap list ethereum.mainnet.usdc.weth.all
swap subscribe ethereum.mainnet.usdc.weth.all

The first query returns historical USDC-WETH swaps, while the second creates a real-time subscription.

Using the all Placeholder

The keyword all serves as a wildcard for any field you don't want to filter on. This allows for flexible queries that can be refined as needed:

CLI examples:

transfer list base.mainnet.usdc.all.all.all   # All historical USDC transfers on Base mainnet
transfer subscribe base.mainnet.usdc.0x123...abc.all.all   # Subscribe to new USDC transfers from a specific address
swap list ethereum.mainnet.all.weth.all   # All historical swaps involving WETH on Ethereum mainnet

REST API examples:

/transfers/list/base.mainnet.usdc.all.all.all   # All historical USDC transfers on Base mainnet
/transfers/subscribe/base.mainnet.usdc.0x123...abc.all.all   # Subscribe to new USDC transfers from a specific address
/swaps/list/ethereum.mainnet.all.weth.all   # All historical swaps involving WETH on Ethereum mainnet

Examples

Below are examples showing both CLI and REST API usage for the same queries:

Events for a Specific Contract

CLI:

event list ethereum.mainnet.0x6B175474E89094C44Da98b954EedeAC495271d0F.Transfer

REST API:

/events/list/ethereum.mainnet.0x6B175474E89094C44Da98b954EedeAC495271d0F.Transfer

Real-time Transfer Monitoring by Token

CLI:

transfer subscribe ethereum.mainnet.dai.all.all.all

REST API:

/transfers/subscribe/ethereum.mainnet.dai.all.all.all

Historical Transfers from a Specific Sender

CLI:

transfer list ethereum.mainnet.usdc.0x123...abc.all.all

REST API:

/transfers/list/ethereum.mainnet.usdc.0x123...abc.all.all

Real-time Swap Monitoring Between Specific Token Pairs

CLI:

swap subscribe ethereum.mainnet.usdc.weth.all

REST API:

/swaps/subscribe/ethereum.mainnet.usdc.weth.all

Why Pattern-based Filtering?

Consistency Across Methods

The same pattern structure works for both historical data retrieval and real-time subscriptions, creating a unified query language for all interactions with Heimdahl.

Cross-Chain Scalability

Our pattern approach provides a unified syntax that works across all supported blockchains while respecting their unique characteristics. Adding support for new chains doesn't change the fundamental query structure.

Parameter Extensibility

As we add support for new filtering parameters, the pattern syntax naturally accommodates them in a consistent way. This future-proofs your integration with Heimdahl.

Readability and Brevity

Patterns using dot notation are more concise and readable than traditional query parameters:

CLI:

# Pattern approach
transfer list ethereum.mainnet.usdc.0x123...abc.all.all

# Traditional query parameters approach would be more verbose
transfer --chain=ethereum --network=mainnet --token=usdc --sender=0x123...abc

REST API:

# Pattern approach
/transfers/list/ethereum.mainnet.usdc.0x123...abc.all.all

# Traditional query parameters
/transfers/list?chain=ethereum&network=mainnet&token=usdc&sender=0x123...abc

Dotted Pattern vs. Flag-based Filtering

Many blockchain APIs use traditional flag or parameter-based filtering. While familiar, this approach has several disadvantages that our dotted pattern syntax addresses:

  1. Simplicity: Dotted patterns create a natural hierarchy that's easy to understand and remember

  2. Consistency: The same pattern structure works across all data types and interfaces

  3. Brevity: Patterns require significantly fewer characters than equivalent flag-based queries

  4. Extensibility: New filtering parameters can be added without changing the API structure

  5. Readability: Patterns visually represent the relationship between filter parameters

For example, a typical flag-based query might look like:

?chain=ethereum&network=mainnet&token=usdc&sender=0x123...abc

While our dotted pattern approach simplifies this to:

ethereum.mainnet.usdc.0x123...abc.all.all

This approach scales much better as your queries become more complex.

Advanced Usage

Pattern Refinement

Start with broader patterns and refine as needed:

CLI:

# Start with all historical USDC transfers
transfer list ethereum.mainnet.usdc.all.all.all

# Refine to specific senders
transfer list ethereum.mainnet.usdc.0x123...abc.all.all

# Subscribe to specific transfers between two addresses
transfer subscribe ethereum.mainnet.usdc.0x123...abc.0x456...def.all

REST API:

# Start with all historical USDC transfers
/transfers/list/ethereum.mainnet.usdc.all.all.all

# Refine to specific senders
/transfers/list/ethereum.mainnet.usdc.0x123...abc.all.all

# Subscribe to specific transfers between two addresses
/transfers/subscribe/ethereum.mainnet.usdc.0x123...abc.0x456...def.all

Implementation Notes

When implementing clients to work with our API, we recommend:

  1. Building pattern-construction utilities to help users create valid patterns

  2. Creating template functions for common queries (list vs. subscribe)

  3. Implementing proper subscription management for real-time data

Conclusion

Our pattern-based filtering approach provides a powerful, consistent, and future-proof way to query blockchain data across different chains and data types. By using the same pattern syntax for both historical (list) and real-time (subscribe) data access, Heimdahl creates a unified experience that simplifies blockchain data integration.

Last updated