Bancor Subgraph

Introducing the Bancor subgraph. This public infrastructure allows developers to query details about the Bancor network activity quickly and easily.

The subgraph is in development - expect changes to make common data pulls easier and bug fixes.

About Bancor

Bancor is a decentralized cross-chain liquidity protocol. Bancor enables peer-to-contract swaps between cryptocurrency assets.

About The Graph

The Graph uses specialized, open source nodes to index and serve data with GraphQL endpoints. You can run these nodes locally or use public endpoints.

About GraphQL

GraphQL is an open source data query language. Its advantage to REST APIs is the ability for developers to specify a complex data structure and have results returned that exactly fit that structure.


Development Status

Last updated February 3, 2020

The Bancor Subgraph is in active development with new deployments based on feedback and issues.

Usage notes

  • Converter { tokenBalances } includes smart tokens with total supply as indicated as a converter balance. Filter these out using Converter { smartToken { id } }
  • SmartToken includes some normal ERC-20 tokens.
  • Not all tokens are ERC-20 compliant. Token details may be missing, including decimals. Implement error handling when converting balances and displaying name or symbols.

Known issues

Submit via hello@blocklytics.org

  • There are inaccurate tokenBalances for a specific set of older converters. Filter these out using this query as a basis.
  • There are inaccurate userTokenBalances for some specific conditions. Avoid relying on this for now.

Using the Bancor Subgraph

Example usage from:

  • Web UI
  • Python
  • React

Web UI

The Graph website offers a tool to query the subgraph. This is suitable for exploring data and planning your own queries.

  • Open subgraph
  • Use the example queries in the drop down menu (top left)
  • Enter your query (left pane)
  • Press the run button (top right) to fetch results (right pane)
The Graph Web UI

Python

Suggested library: https://pypi.org/project/graphqlclient/

Sample query to get converters and their current balances:

from graphqlclient import GraphQLClient
import json

# Use this for the current version
ENDPOINT = "https://api.thegraph.com/subgraphs/name/blocklytics/bancor"

client = GraphQLClient(ENDPOINT)

QUERY = """
{
  converters(first:50, skip:0) {
    id
    smartToken {
      id
      symbol
      decimals
    }
    tokenBalances {
      token {
        id
        symbol
        decimals
      }
      balance
    }
  }
}
"""

result = json.loads(client.execute(QUERY))
converters = result['data']['converters']

for converter in converters:
    # Skip empty converters
    if len(converter['tokenBalances']) == 0:
        continue
        
    converter_address = converter['id']
    smart_token_address = converter['smartToken']['id']
    smart_token_symbol = converter['smartToken']['symbol']
    smart_token_decimals = converter['smartToken']['decimals']
    print("Converter: {0}\nSmart token: {1}\n".format(
        converter_address,
        smart_token_symbol
    ))
    for tokenBalance in converter['tokenBalances']:
        balance = tokenBalance['balance']
        token = tokenBalance['token']['id']
        symbol = tokenBalance['token']['symbol']
        decimals = tokenBalance['token']['decimals']
        balance_converted = float(balance) / 10 ** float(decimals)
        print("{2:,.0f} {1} ({0})".format(
            token, symbol, balance_converted
        ))
    print("------\n")

React

Suggested library: https://www.apollographql.com/docs/react/get-started/

import React from 'react';
import { useQuery } from '@apollo/react-hooks';
import ApolloClient, { gql } from 'apollo-boost';

// Use this for the current version
const ENDPOINT = "https://api.thegraph.com/subgraphs/name/blocklytics/bancor"

const client = new ApolloClient({
  uri: ENDPOINT,
});

const QUERY = gql`
    {
      converters(
        first: 10, skip: 0,
        orderBy:bntBalance,
        orderDirection:desc,
        where:{ bntBalance_not:null }) {
        id
        smartToken {
          id
          name
          decimals
        }
        conversionFee
        bntBalance
        tokenBalance
        weight
      }
    }
`;

function ExchangeRates() {
  const { loading, error, data } = useQuery(QUERY);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error :(</p>;

  return data.converters.map(({ id, bntBalance, tokenBalance }) => (
    <div key={id}>
      <p>
        {id}: {bntBalance / tokenBalance}
      </p>
    </div>
  ));
}