Step-By-Step: Fetching Historical Data

Supercharge your DeFi & Web3 project with the Portals API Historical Data Endpoints.

July 22, 2024

Looking to build a price chart for your dashboard, integrate historical data into your DeFi application, or analyze token performance over time? These endpoints provide powerful tools for accessing a comprehensive token history. This guide demonstrates how to use the Historical Data endpoint in the Portals API to retrieve historical token data across multiple networks.

What is the Portals API?


Imagine a user-friendly DeFi API with straightforward endpoints delivering comprehensive data, with which a single query can fetch balances across all networks, or returns every single asset associated with a DeFi platform. That's the Portals API. In a single integration, the API allows you to inject your app with coverage of thousands of tokens & DeFi assets across 9 EVMs & hundreds of protocols from Aave to Yearn and everything in between.

And the best part? Most devs can start building with Portals API in under 30 minutes!

Let's get started.

Example API Response


Before we dive into the implementation details, let's take a look at what you'll get when you successfully call the Historical Token Data endpoint.

Here's an example of the JSON response:

[json]
{
 "pageItems": 24,
 "totalItems": "24",
 "more": false,
 "page": 0,
 "history": [
   {
     "time": "2024-07-12T11:00:00.000Z",
     "highPrice": "1.0217005980196371",
     "lowPrice": "1.0214397344342721",
     "openPrice": "1.0214668062561276",
     "closePrice": "1.0215308614304874",
     "liquidity": "2939806.6644586953",
     "reserves": [
       "2940768.2956913866270687851"
     ],
     "totalSupply": "2877844.1997748123433518881",
     "pricePerShare": "1.0218650112891788981",
     "volume1dUsd": "-5918.5362559179002957463350411",
     "apy": "7.715"
   },
   {
     "time": "2024-07-12T10:00:00.000Z",
     "highPrice": "1.0218306948814526",
     "lowPrice": "1.0209634374421843",
     "openPrice": "1.0209634374421843",
     "closePrice": "1.0218306948814526",
     "liquidity": "2940691.8357156995",
     "reserves": [
       "2941653.4669483909122356476"
     ],
     "totalSupply": "2878720.3010315086791187506",
     "pricePerShare": "1.0219951481494049904",
     "volume1dUsd": "-5918.5362559179002957463350411",
     "apy": "7.715"
   }
 ]
}
[/json]


This response includes:

1) Pagination information (pageItems, totalItems, more, page)

2) A history array containing data points for each time interval

3) Each data point includes:
  • Timestamp (time)
  • Price information (highPrice, lowPrice, openPrice, closePrice)
  • Liquidity
  • Token reserves in the pool (reserves)
  • Total supply of the token (totalSupply)
  • Price per share for yield-bearing tokens (pricePerShare)
  • 24-hour trading volume in USD (volume1dUsd)
  • Annual Percentage Yield for yield-bearing tokens (apy)


API Endpoint Details

Method: GET
Base URL: https://api.portals.fi/v2/tokens/history
Purpose: Returns historical data for specified tokens, including price, liquidity, and other metrics.
Swagger Documentation: Supported Controller getTokenHistory


Making API Requests

‣Request Parameters

To fetch historical token data, you'll need to provide the following parameters:


‣Token Identification

The API requires tokens to be identified using a specific format: [network]:[address].

For example: ethereum:0x028ec7330ff87667b6dfb0d94b954c820195336c

This format allows you to specify both the network and the token address in a single parameter.

‣Time Resolution

You can specify the time resolution for the historical data using the resolution parameter. Available options are:

15m: 15-minute intervals
1h: Hourly data
4h: 4-hour intervals
1d: Daily data (default)


Setting Up Your Environment


First, let's set up a TypeScript project. If you don't have TypeScript installed, you can do so by running:

[bash]
npm install -g typescript
[/bash]


Next, create a new directory for your project and initialize a new Node.js project:

[bash]
mkdir historical-token-data
cd historical-token-data
npm init -y
[/bash]


Now, install Axios and TypeScript:

[bash]
npm install axios
npm install --save-dev typescript @types/node @types/axios
[/bash]


Create a tsconfig.json file in the root directory to configure TypeScript:

[json]
{
 "compilerOptions": {
   "target": "ES6",
   "module": "commonjs",
   "strict": true,
   "esModuleInterop": true,
   "skipLibCheck": true,
   "forceConsistentCasingInFileNames": true
 },
 "include": ["src"]
}
[/json]

Passing the API Key


The Portals API requires authentication via an API key. Here's how you can pass the API key using Axios:

1) Obtain your API key from the Portals API dashboard.
2) Store the API key in an environment variable:
  - Install the dotenv package: npm install dotenv
  - Create a .env file in the root of your project and add your API key:
 
[bash]
PORTALS_API_KEY=your_api_key_here
[/bash]

Writing the TypeScript Script


Create a file named fetchHistoricalTokenData.ts in the src directory and add the following code:

[ts]
import axios from "axios";
import * as dotenv from "dotenv";
dotenv.config();

const BASE_URL = "https://api.portals.fi/v2/tokens/history";

interface HistoryDataPoint {
 time: string;
 highPrice: string;
 lowPrice: string;
 openPrice: string;
 closePrice: string;
 liquidity: string;
 reserves: string[];
 totalSupply: string;
 pricePerShare: string;
 volume1dUsd: string;
 apy: string;
}

interface HistoricalData {
 pageItems: number;
 totalItems: string;
 more: boolean;
 page: number;
 history: HistoryDataPoint[];
}

const API_KEY = process.env.PORTALS_API_KEY;

const axiosInstance = axios.create({
 headers: { Authorization: `Bearer ${API_KEY}` },
});

async function fetchHistoricalTokenData(
 tokenId: string,
 from: number,
 resolution: string
): Promise<HistoricalData> {
 try {
   const response = await axiosInstance.get(BASE_URL, {
     params: { id: tokenId, from: from, resolution: resolution },
   });
   return response.data;
 } catch (error) {
   console.error(`Error fetching historical token data: ${error}`);
   throw error;
 }
}

// Example usage
const main = async () => {
 const tokenId = "ethereum:0x028ec7330ff87667b6dfb0d94b954c820195336c"; // Yearn V3 DAI-1 yVault
 const oneWeekAgo = Math.floor(Date.now() / 1000) - 7 * 24 * 60 * 60;
 const resolution = "1d";

 try {
   const historicalData = await fetchHistoricalTokenData(
     tokenId,
     oneWeekAgo,
     resolution
   );
   console.log(
     "Historical Token Data:",
     JSON.stringify(historicalData, null, 2)
   );
 } catch (error) {
   console.error("Error in main function:", error);
 }
};

main();
[/ts]

Running the Script


To run the script, compile it to JavaScript using TypeScript and then execute it with Node.js:

[bash]
tsc
node dist/fetchHistoricalTokenData.js
[/bash]

You should see an output with the historical data of the specified token.

Understanding the Response


A successful API call returns a JSON object containing historical data for the specified token. The response includes pagination information and an array of history objects, each representing a data point at the specified resolution.

Key properties of a history object include:

time: Timestamp for the data point
highPrice, lowPrice, openPrice, closePrice: Price information
liquidity: Token liquidity at the end of the period
reserves: Token reserves in the pool
totalSupply: Total supply of the token
pricePerShare: Price per share (for yield-bearing tokens)
volume1dUsd: 24-hour trading volume in USD
apy: Annual Percentage Yield (for yield-bearing tokens)

Best Practices & Optimization


To ensure efficient use of the API and optimal performance in your applications, consider the following practices:

1) Appropriate Resolution: Choose the resolution that best fits your use case. Using a lower resolution (e.g., 1d instead of 15m) when possible can reduce data transfer and processing time.
2) Caching: Implement caching for historical data, especially for older time periods that are unlikely to change.
3) Pagination: Utilize the pagination features (page parameter) when dealing with large datasets to improve response times and manage memory usage effectively.

Congratulations!


The Historical Data endpoint provides incredible insights into token performance over time, but that’s only the tip of the iceberg in terms of possibilities. By following these guidelines and best practices, you can effectively integrate this functionality into your DeFi & Web3 applications with minimal effort, ensuring efficient and reliable access to comprehensive historical token data.

Still having trouble? Join like-minded developers and API users on our official Discord: https://discord.gg/JKDYTXN8hm

Stay tuned for more tutorials on how to leverage the power of DeFi with the Portals API!