Flipside Docs
  • Welcome to Flipside!
    • Welcome to Flipside
    • Growth Services
    • Data
      • Choose your Flipside plan
        • Free
        • Builder
        • Pro
          • Get Started in Snowflake
          • Incremental Table Pattern
          • Copy Data from Snowflake to AWS
          • Copy Data from Snowflake to GCP
          • Copy Data from Snowflake to Azure
        • Snowflake Data Shares
          • Mounting a Snowflake Data Share
    • Earn
    • Community
  • Data
    • Flipside Data
      • Table Docs by Chain
      • Data Modeling Approach
      • Labels
        • Centralized Exchange Label Type
        • Decentralized Exchange Label Type
        • Operator Label Type
        • Chain Admin Label Type
        • Decentralized Finance Label Type
        • NonFungible Tokens Label Type
        • Games Label Type
        • Bridge Label Type
        • Decentralized Applications Label Type
        • Token Label Type
        • Flotsam Label Type
      • Tags
      • Table Freshness Targets
      • Contribute to Our Data
        • Contract Decoding & ABIs
        • How to Add Your Own Tags
        • Community Curation
          • Getting Started
            • Contribution Workflow
          • Model Standards
            • dbt Tips
          • PR Checklist
    • Data Products
      • Data Studio (SQL Analysts)
        • Get Started
          • Write/fork your first query
        • Flipside AI
        • Studio in Depth
          • Query Editor
            • Query Referencing
            • Pro Tips for Querying
            • Keyboard Shortcuts
            • Hex-to-Integer Function
          • Create a Chart
            • Advanced Visualization
          • Build a Dashboard
            • Markdown Reference
          • Team Accounts
        • Tutorials
          • How to Analyze Web3 Data
          • Video Tutorials
            • Overview of Schemas & Tables
            • Ethereum Tutorials
              • Getting Started with Decoded Ethereum Events
              • Getting Started with Ethereum Balances
              • Block Level and Daily Balances
              • Finding Centralized Exchange Flows
            • Solana Tutorials
              • Solana Schema & Tables: Video Walkthrough
              • Solana Specialty Tables: Video Walkthrough
              • Exploring Transactions in solana.events
            • THORChain Tutorials
              • THORChain Schema & Tables
              • Calculating IL for THORChain
          • More Tools & Resources
        • Get Inspired
      • LiveQuery
        • Get Started
        • LiveQuery in Depth
          • Functions
            • 🤝Partner Functions
            • 🧙‍♂️EVM Functions
              • 💡Seaport: Real-time Orders
              • 💡WETH Pool Balances
              • 💡General EVM Node Queries
            • 🤖API Functions
              • 💡Query TheGraph
              • 💡Query Defi Llama
            • ⚙️Utility Functions
              • 💡Hex Converters
              • 💡JSON RPC Request Builder
              • 💡EVM Logs Decoder
              • 💡Keccak256 Encoder
          • QuickNode Setup Guide
        • Secrets Manager
        • Get Inspired
      • Snowflake
      • API/SDK (Developers)
        • Get Started - Your first API call in < 2 min
        • SDK in Depth
          • JSON RPC methods
          • Run A Query
          • Query Results
          • Pagination
          • Sorting
          • Filtering
          • Query Seconds
          • Caching (maxAgeMinutes)
          • Rate Limits
          • Errors
          • More Examples
          • Archive
            • [ARCHIVED] JS/TS SDK
            • ShroomDK Migration Guide
            • [LEGACY] R
        • Tutorials
          • Have Questions?
        • Get Inspired
    • Insights and Tools
  • Earn
    • Flipside Earn
    • Onchain Rewards
      • Quests
    • Analyst Rewards
      • Top Dashboards
        • Top Dashboard Guidelines
        • Skill Tree
      • Ambassador Program
      • Direct to Analyst Commissions
    • Wallet Management
    • Tax Center
  • Support
    • General Support
    • Open a Ticket
      • That email doesn't look quite right
    • 🌟Product Special Releases
      • 2025
        • 2025-02-06 | EVM Blockchain Standardization
          • Table Change Overview
      • 2024
        • 2024-06-13 | Solana native and wrapped addresses
        • 2024-05-01 | Improvements to Pricing Data
          • Actions for Data Studio Users
          • Actions for API Users
          • Action for Data Share Users
    • 🗒️Release Notes
      • 2025
        • 2025-05-01 | Release Notes
        • 2025-04-17 | Release Notes
        • 2025-04-03 | Release Notes
        • 2025-03-20 | Release Notes
        • 2025-03-06 | Release Notes
        • 2025-02-20 | Release Notes
        • 2025-02-06 | Release Notes
        • 2025-01-23 | Release Notes
      • 2024
        • 2024-12-24 | Release Notes
        • 2024-12-12 | Release Notes
        • 2024-11-27 | Release Notes
        • 2024-11-14 | Release Notes
        • 2024-10-31 | Release Notes
        • 2024-10-03 | Release Notes
        • 2024-10-17 | Release Notes
        • 2024-09-19 | Release Notes
        • 2024-09-05 | Release Notes
        • 2024-08-22 | Release Notes
        • 2024-08-08 | Release Notes
        • 2024-07-25 | Release Notes
        • 2024-07-11 | Release Notes
        • 2024-06-27 | Release Notes
        • 2024-06-14 | Release Notes
        • 2024-05-30 | Release Notes
        • 2024-05-16 | Release Notes
        • 2024-05-02 | Release Notes
        • 2024-04-18 | Release Notes
        • 2024-04-05 | Release Notes
        • 2024-03-18 | Release Notes
        • 2024-03-05 | Release Notes
        • 2024-02-20 | Release Notes
        • 2024-02-05 | Release Notes
    • 📊Studio Change log
  • Flipside Community
    • Get Started
    • Ambassador Program
    • Join Our Discord
    • Join Our Guild
Powered by GitBook
On this page
  • 💾 Install the SDK
  • 🦾 Getting Started
  • The Details

Was this helpful?

  1. Data
  2. Data Products
  3. API/SDK (Developers)
  4. SDK in Depth
  5. Archive

[ARCHIVED] JS/TS SDK

PreviousArchiveNextShroomDK Migration Guide

Last updated 1 year ago

Was this helpful?

To skip the walkthrough and go straight to dedicated API Documentation, .

💾 Install the SDK

yarn add @flipsidecrypto/sdk

or if using npm

npm install @flipsidecrypto/sdk

🦾 Getting Started

import { Flipside, Query, QueryResultSet } from "@flipsidecrypto/sdk";

// Initialize `Flipside` with your API key
const flipside = new Flipside(
  "<YOUR_API_KEY>",
  "https://api-v2.flipsidecrypto.xyz"
);

// Parameters can be passed into SQL statements via simple & native string interpolation
const myAddress = "0x....";

// Create a query object for the `query.run` function to execute
const query: Query = {
  sql: `select nft_address, mint_price_eth, mint_price_usd from flipside_prod_db.ethereum_core.ez_nft_mints where nft_to_address = LOWER('${myAddress}')`,
  maxAgeMinutes: 30,
};

// Send the `Query` to Flipside's query engine and await the results
const result: QueryResultSet = await flipside.query.run(query);

// Iterate over the results
result.records.map((record) => {
  const nftAddress = record.nft_address
  const mintPriceEth = record.mint_price_eth
  const mintPriceUSD = = record.mint_price_usd
  console.log(`address ${nftAddress} minted at a price of ${mintPrice} ETH or $${mintPriceUSD} USD`);
});

The Details

The Query Object

The Query object contains both the sql and configuration you can send to the query engine for execution.

type Query = {
  // SQL query to execute
  sql: string;

  // The number of minutes you are willing to accept cached
  // result up to. If set to 30, if cached results exist within
  // the last 30 minutes the api will return them.
  maxAgeMinutes?: number;

  // An override on the query result cahce.
  // A value of false will re-execute the query and override
  // maxAgeMinutes
  cached?: boolean;

  // The number of minutes until your query run times out
  timeoutMinutes?: number;

  // The number of records to return, defaults to 100000
  pageSize?: number;

  // The page number to return, defaults to 1
  pageNumber?: number;

  // The owner of the data source (defaults to 'flipside')
  dataProvider?: string;

  // The data source to execute the query against (defaults to 'snowflake-default')
  dataSource?: string;
};

Let's create a query to retrieve all NFTs minted by an address:

const yourAddress = "<your_ethereum_address>";

const query: Query = {
  sql: `select nft_address, mint_price_eth, mint_price_usd from flipside_prod_db.ethereum_core.ez_nft_mints where nft_to_address = LOWER('${myAddress}')`,
  maxAgeMinutes: 5,
  cached: true,
  timeoutMinutes: 15,
  pageNumber: 1,
  pageSize: 10,
};

Now let's execute the query and retrieve the results.

const result: QueryResultSet = await flipside.query.run(query);

The results of this query will be cached for 60 minutes, given the ttlMinutes parameter.

The QueryResultSet Object

After executing a query the results are stored in a QueryResultSet object.

interface QueryResultSet {
  // The server id of the query
  queryId: string | null;

  // The status of the query (`PENDING`, `FINISHED`, `ERROR`)
  status: QueryStatus | null;

  // The names of the columns in the result set
  columns: string[] | null;

  // The type of the columns in the result set
  columnTypes: string[] | null;

  // The results of the query
  rows: any[] | null;

  // Summary stats on the query run (i.e. the number of rows returned, the elapsed time, etc)
  runStats: QueryRunStats | null;

  // The results of the query transformed as an array of objects
  records: QueryResultRecord[] | null;

  // The page of results
  page: PageStats | null;

  // If the query failed, this will contain the error
  error:
    | ApiError
    | QueryRunRateLimitError
    | QueryRunTimeoutError
    | QueryRunExecutionError
    | ServerError
    | UserError
    | UnexpectedSDKError
    | null;
}

Let's iterate over the results from our query above. Our query selected nft_address, mint_price_eth, and mint_price_usd. We can access the returned data via the records parameter. The column names in our query are assigned as keys in each record object.

result.records.map((record) => {
  const nftAddress = record.nft_address;
  const mintPriceEth = record.mint_price_eth;
  const mintPriceUSD = record.mint_price_usd;
  console.log(
    `address ${nftAddress} minted at a price of ${mintPriceEth} ETH or $${mintPriceUSD} USD`
  );
});

Pagination

To page over the results use the getQueryResults method.

// what page are we starting on?
let currentPageNumber = 1

// How many records do we want to return in the page?
let pageSize = 1000

// set total pages to 1 higher than the `currentPageNumber` until
// we receive the total pages from `getQueryResults` given the 
// provided `pageSize` (totalPages is dynamically determined by the API 
// based on the `pageSize` you provide)
let totalPages = 2

// we'll store all the page results in `allRows`
let allRows = []

while (currentPageNumber <= totalPages) {
  results = await flipside.query.getQueryResults({
    queryRunId: result.queryId,
    pageNumber: currentPageNumber,
    pageSize: pageSize
  })
  totalPages = results.page.totalPages
  allRows = [...allRows, ...results.records]
  currentPageNumber += 1
}

Sort the Results

Let's fetch the results sorted in descending order by mint_price_usd.

results = await flipside.query.getQueryResults({
  queryRunId: result.queryId,
  pageNumber: 1,
  pageSize: 1000,
  sortBy: [
    {
      column: 'mint_price_usd',
      direction: 'desc'
    }
  ]
})

Valid directions include desc and asc. You may also sortBy multiple columns. The order you provide the sortBy objects determine which sortBy object takes precedence.

The following example will first sort results in descending order by mint_price_usd and then in ascending order by nft_address.

results = await flipside.query.getQueryResults({
  queryRunId: result.queryId,
  pageNumber: 1,
  pageSize: 1000,
  sortBy: [
    {
      column: 'mint_price_usd',
      direction: 'desc'
    },
    {
      column: 'nft_address',
      direction: 'asc'
    }
  ]
})

For reference here is the SortBy type:

interface SortBy {
  column: string;
  direction: "desc" | "asc";
}

Filter the results

Now let's filter the results where mint_price_usd is greater than $10

results = await flipside.query.getQueryResults({
  queryRunId: result.queryId,
  pageNumber: 1,
  pageSize: 1000,
  filters: [
    {
      gt: 10,
      column: 'mint_price_usd'
    }
  ]
})

Filters can be applied for: equals, not equals, greater than, greater than or equals to, less than, less than or equals to, like, in, not in. All filters are executed server side over the entire result set.

Here is the Filter type:

interface Filter {
  column: string;
  eq?: string | number | null;
  neq?: string | number | null;
  gt?: number | null;
  gte?: number | null;
  lt?: number | null;
  lte?: number | null;
  like?: string | number | null;
  in?: any[] | null;
  notIn?: any[] | null;
}

Understanding MaxAgeMinutes (and caching of results)

The parameter maxAgeMinutes can be used to control whether a query will re-execute or return cached results. Let's talk thru an example.

Set maxAgeMinutes to 30:

const query: Query = {
  sql: `select nft_address, mint_price_eth, mint_price_usd from flipside_prod_db.ethereum_core.ez_nft_mints where nft_to_address = LOWER('${myAddress}')`,
  maxAgeMinutes: 30
};

Behind the scenes the Flipside API will hash the sql text and using that hash determine if results exist that were recorded within the last 30 minutes. If no results exist, or the results that exist are more than 30 minutes old the query will re-execute.

If you would like to force a cache bust and re-execute the query. You have two options, either set maxAgeMinutes to 0 or pass in cache=false. Setting cache to false effectively sets maxAgeMinutes to 0.

const query: Query = {
  sql: `select nft_address, mint_price_eth, mint_price_usd from flipside_prod_db.ethereum_core.ez_nft_mints where nft_to_address = LOWER('${myAddress}')`,
  maxAgeMinutes: 0
};

// or:
const query: Query = {
  sql: `select nft_address, mint_price_eth, mint_price_usd from flipside_prod_db.ethereum_core.ez_nft_mints where nft_to_address = LOWER('${myAddress}')`,
  maxAgeMinutes: 30,
  cache: false
};

Understanding Query Seconds

You can determine how many execution seconds your query took by looking at the runStats object on the QueryResultSet.

const runStats = result.runStats

There are a number of stats returned:

type QueryRunStats = {
  startedAt: Date;
  endedAt: Date;
  elapsedSeconds: number;
  queryExecStartedAt: Date;
  queryExecEndedAt: Date;
  streamingStartedAt: Date;
  streamingEndedAt: Date;
  queuedSeconds: number;
  streamingSeconds: number;
  queryExecSeconds: number;
  bytes: number; // the number of bytes returned by the query
  recordCount: number;
};

Your account is only debited for queryExecSeconds. This is the number of computational seconds your query executes against Flipside's data warehouse.

const execSeconds = runStats.queryExecSeconds

You are only debited when the query is executed. So if you set maxAgeMinutes to a value greater than 0, and the query does not re-execute then you will only be charged for the time it executes.

Flipside does NOT charge for the number of bytes/records returned.

Client Side Request Requirements

All API Keys correspond to a list of hostnames. Client-side requests that do not originate from the corresponding hostname will fail. You may configure hostnames .

here
click here
tests