Skip to content

Pangea API

Historical and real-time streaming of indexed data using the Pangea client.

Getting started

Request your Passport

Join our Discord and request your Pangea Passport.

Add your credentials

Create a .env file in your project root directory and define your credentials:

PANGEA_USERNAME=xxxxx
PANGEA_PASSWORD=xxxxx

Install the Pangea client

Rust
cargo add pangea-client

Start building

This example streams prices from the Uniswap V3 USDC/WETH 5bps pool.

Code

Rust
// Step 1: Import dependencies
use futures::StreamExt;
use std::{collections::HashSet, sync::Arc};
use pangea_client::{
    core::types::ChainId, query::Bound,
    ClientBuilder, Format, WsProvider,
    provider::UniswapV3Provider, requests::uniswap_v3::GetPricesRequest  // Get data from the Uniswap V3 Prices toolbox
};
 
 
#[tokio::main]
async fn main() {
    // Step 2: Load environment variables
    dotenvy::dotenv_override().ok();
 
    // Step 3: Initialize the client
    let client = match ClientBuilder::default()
        .endpoint("app.pangea.foundation") // Set the endpoint
        .build::<WsProvider>()
        .await
    {
        Ok(client) => Arc::new(client),
        Err(e) => {
            eprintln!("Client failed to initialize:\n{e}");
            return;
        }
    };
 
    // Step 4: Create and send request
    {
        let request = GetPricesRequest { // Get prices data
            chains: HashSet::from([ChainId::ETH]), // On Ethereum mainnet
            from_block: Bound::FromLatest(1000), // Start the stream 1000 blocks from the latest block
            to_block: Bound::Subscribe, // Subscribe to real-time stream
            pool_address__in: HashSet::from(["0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640" // Filter on the USDC/WETH 5bps pool
                .parse()
                .unwrap()]),
            ..Default::default()
        };
        let stream = match client
            .get_prices_by_format(request, Format::JsonStream, false) // Return JSONStream format
            .await
        {
            Ok(stream) => stream,
            Err(e) => {
                eprintln!("Request failed\n{e}");
                return;
            }
        };
 
        futures::pin_mut!(stream);
 
        // Step 5: Stream and print output
        while let Some(chunk) = stream.next().await {
            let chunk = String::from_utf8(chunk.unwrap()).unwrap();
            println!("{chunk}");
        }
    }
}

Response

{
    chain: 1,
    block_number: 22896999,
    block_hash: '0x10cbf7f2674c54baa3dc062ae8e18a6de5c527ecddc51787d7cebb38cbc74d6b',
    transaction_hash: '0x6db5bb7e60f532e9ed14fb78c9ed03084a4a1a70f9994357cf03747bff1ca3aa',
    transaction_index: 2,
    log_index: 41,
    pool_address: '0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640',
    virtual0: 1.8451065547937724e-15,
    virtual1: 3.904927454923885e+51,
    price: 2965.9761137086434,
    sender: '0x51c72848c68a965f66fa7a88855f9f7784502a7f',
    receiver: '0x51c72848c68a965f66fa7a88855f9f7784502a7f',
    amount0: 110958.214084,
    amount1: -37.420036648501004,
    liquidity: 2684214455492374500,
    tick: 196370,
    token0_address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
    token0_decimals: 6,
    token0_name: 'USD//C',
    token0_symbol: 'USDC',
    token1_address: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
    token1_decimals: 18,
    token1_name: 'Wrapped Ether',
    token1_symbol: 'WETH',
    timestamp: 1752249779
}
...

Chain selection

Each chain is identified by an endpoint and ChainId which must be configured.

Set the endpoint

Set the endpoint upon client initialisation.

Rust
.endpoint("app.pangea.foundation")

Set the ChainId

Set the ChainId in the request query parameters.

Rust
chains: HashSet::from([ChainId::ETH]),

Dataset selection

Select which dataset to request data from.

In Rust, you need to use the provider and the requests:

Rust
provider::UniswapV3Provider, requests::uniswap_v3::GetPricesRequest

Then make your request:

Rust
let request = GetPricesRequest {

And use the method name:

Rust
.get_prices_by_format(request, Format::JsonStream, false)

In NodeJS and Python, you only need to make the request:

NodeJS
const handle = await client.get_uniswap_v3_prices(

Query parameters

Requests are filtered using query parameters, which are either mandatory or optional.

Rust
let request = GetPricesRequest {
        chains: HashSet::from([ChainId::ETH]), 
        from_block: Bound::FromLatest(1000), 
        to_block: Bound::Subscribe, 
        pool_address__in: HashSet::from(["0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"
        .parse() 
        .unwrap()]), 
        ..Default::default() 
    };

ChainId

Block range

To request data between two specific blocks, use positive integer values:

Rust
from_block: Bound::Exact(21000000),
to_block: Bound::Exact(21010000),

To request data at the latest available block, use Latest (in Rust) or "latest" (in NodeJS and Python):

Rust
from_block: Bound::Exact(21000000),
to_block: Bound::Latest,

To subscribe to a real-time stream of data, use Subscribe (in Rust) or "none" (in NodeJS and Python) as the value for to_block:

Rust
from_block: Bound::Exact(21000000),
to_block: Bound::Subscribe,

To request data for an exact range from the latest available block, use a negative integer as the from_block value in combination with either Latest (in Rust) or "latest" (in NodeJS and Python), or with Subscribe (in Rust) or "none" (in NodeJS and Python), as the to_block value.

Rust
from_block: Bound::Exact(-10000),
to_block: Bound::Latest,

Optional parameters

Each dataset has its own optional query parameters, detailed descriptions of which can be found in the API reference documentation.

Parameters with the __in suffix accept a list of values.

Parameters with the __gte or __lte suffix will return values greater/less than or equal to the provided value.

Complex queries can be achieved by combining any number of different query parameters.

Response format

Set the reponse format for the request.

Json, JsonStream, and Arrow-IPC formats are supported.

Rust
.get_prices_by_format(request, Format::JsonStream, false)

Getting help

If you have any questions, join our Discord and get help from the community.