This tutorial will help you build a TradingView chart app with blockchain data from Bitquery.
Price Index for DEX Tokens
The tutorial uses the token ADVT, which is not traded against USDT. As a result, we obtain the WETH<>ADVT price and use it to calculate the token’s price in USDT. However, if your chosen token is traded against USDT, you can accomplish this in a single query.
Query 1: Get ADVT price against WETH
query MyQuery {
ethereum(network: ethereum) {
dexTrades(
quoteCurrency: {is: "0xdac17f958d2ee523a2206206994597c13d831ec7"}
baseCurrency: {is: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"}
options: {limit: 1, desc: "block.height"}
) {
timeInterval {
minute(count: 15, format: "%Y-%m-%dT%H:%M:%SZ")
}
buyCurrency: baseCurrency {
symbol
address
}
sellCurrency: quoteCurrency {
symbol
address
}
sellAmountInUsd: quoteAmount
tradeAmount(in: USD)
averageQuotePrice: quotePrice(calculate: average)
block {
height
}
}
}
}
Query 2: Get WETH price against USDT
query: `
{
ethereum(network: ethereum) {
dexTrades(
options: {asc: "timeInterval.minute"}
date: {since: "2021-06-20T07:23:21.000Z", till: "2023-04-03T15:23:21.000"}
baseCurrency: {is: "0x69e37422cb87d963367f73a119c8ce9a4d529b72"}
quoteCurrency: {is: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"}
tradeAmountUsd: {gt: 10}
exchangeName: {is: "Uniswap"}
) {
timeInterval {
minute(count: 15, format: "%Y-%m-%dT%H:%M:%SZ")
}
volume: quoteAmount
high: quotePrice(calculate: maximum)
low: quotePrice(calculate: minimum)
open: minimum(of: block, get: quote_price)
close: maximum(of: block, get: quote_price)
}
}
}
A Step-by-step guide to building the Tradingview app
Bitquery.js
Import the necessary files
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { createChart } from 'lightweight-charts';
Define the TradingViewData component:
export function TradingViewData() {
// Component logic will go here
}
Set up state variables
Inside the TradingViewData component, add the following state variables using the useState hook:
const [tradingData, setTradingData] = useState(null);
const [WETHprice, setWETHprice] = useState(null);
We use two functions to fetch the data.
The fetchMyQueryData function uses the axios library to fetch the WETH<>USDT price from the Bitquery API.
const fetchMyQueryData = async () => {
try {
const response = await axios.post(
'https://graphql.bitquery.io',
{
query: `
query MyQuery {
ethereum(network: ethereum) {
dexTrades(
quoteCurrency: {is: "0xdac17f958d2ee523a2206206994597c13d831ec7"}
baseCurrency: {is: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"}
options: {limit: 1, desc: "block.height"}
) {
timeInterval {
minute(count: 15, format: "%Y-%m-%dT%H:%M:%SZ")
}
buyCurrency: baseCurrency {
symbol
address
}
sellCurrency: quoteCurrency {
symbol
address
}
sellAmountInUsd: quoteAmount
tradeAmount(in: USD)
averageQuotePrice: quotePrice(calculate: average)
block {
height
}
}
}
}
`
},
{
headers: {
'Content-Type': 'application/json',
'X-API-KEY': 'YOUR KEY'
}
}
);
setWETHprice(response.data?.data?.ethereum.dexTrades[0]?.averageQuotePrice);
} catch (error) {
console.log(error);
}
};
The fetchMyQueryData function is called immediately after the component is mounted. This ensures that the WETH<>USDT price is fetched before the chart is created.
The useEffect hook is used to call the fetchData function whenever the tradingData or WETHprice state variables change. This ensures that the chart is updated whenever the trading data changes.
useEffect(() => {
const fetchData = async () => {
try {
const response = await axios.post(
'https://graphql.bitquery.io',
{
query: `
{
ethereum(network: ethereum) {
dexTrades(
options: {asc: "timeInterval.minute"}
date: {since: "2021-06-20T07:23:21.000Z", till: "2023-04-03T15:23:21.000"}
baseCurrency: {is: "0x69e37422cb87d963367f73a119c8ce9a4d529b72"}
quoteCurrency: {is: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"}
tradeAmountUsd: {gt: 10}
exchangeName: {is: "Uniswap"}
) {
timeInterval {
minute(count: 15, format: "%Y-%m-%dT%H:%M:%SZ")
}
volume: quoteAmount
high: quotePrice(calculate: maximum)
low: quotePrice(calculate: minimum)
open: minimum(of: block, get: quote_price)
close: maximum(of: block, get: quote_price)
}
}
}
`
},
{
headers: {
'Content-Type': 'application/json',
'X-API-KEY': 'YOUR KEY'
}
}
);
setTradingData(response.data);
} catch (error) {
console.log(error);
}
};
fetchData();
}, []);
Get your API here Bitquery
Calculate token prices
Add another useEffect hook to calculate the prices of the DEX tokens based on the WETH<>USDT price and the retrieved trading data:
useEffect(() => {
if (tradingData && WETHprice) {
const data = tradingData.data.ethereum.dexTrades.map((trade) => {
const open = Number(trade.open) * WETHprice * 1000000; // Scale up the number by 1,000,000
const high = Number(trade.high) * WETHprice * 1000000;
const low = Number(trade.low) * WETHprice * 1000000;
const close = Number(trade.close) * WETHprice * 1000000;
return {
time: new Date(trade.timeInterval.minute).getTime() / 1000,
open,
high,
low,
close,
volume: Number(trade.volume),
};
});
const chart = createChart(document.getElementById('firstContainer'), { priceScale: 10 });
const candlestickSeries = chart.addCandlestickSeries();
candlestickSeries.setData(data);
}
}, [tradingData, WETHprice]);
Render the chart
Finally, render the chart using the TradingViewData component:
return (
<div>
{tradingData ? (
<div id="firstContainer" style={{ height: 600, width: '100%' }}></div>
) : (
<p>Loading...</p>
)}
</div>
);
App
App.js file renders the component
import './App.css';
import {TradingViewData} from './bitquery'
function App() {
return (
<div className="App">
<TradingViewData/>
</div>
);
}
export default App;
That’s it! You have now implemented a tradingview clone for blockchain data. Make sure to replace ‘YOUR KEY’ in the code with your actual API key to fetch the data correctly.
This is how it will look finally!
The full code is available in this repo here GitHub - bitquery/Tradingview-Application