Build Your First ETH Dashboard App with Python Dash

This tutorial presents the newest dashboard app to visualize Ethereum data from Adam’s CharmingData channel:

Adam is the lead author of our book Plotly Dash — you can check it out here:

But first things first: What is Plotly Dash anyway? πŸ“ˆ Dash is a Python framework for building analytical web applications, and Plotly is a graphing library for making interactive plots.

As you read through this tutorial, feel free to watch Adam’s excellent video explanation:

Let’s dive into the code from the GitHub, I’ll explain it in a minute. Here’s the high-level summary:

πŸ’‘ TLDR: This code is a Dash web application that displays live gas prices on the Ethereum blockchain, a line chart showing Ethereum’s value over time, and a line chart showing the number of active Ethereum addresses over time.

from dash import Dash, html, dcc, Input, Output, callback  # pip install dash
import dash_bootstrap_components as dbc                    # pip install dash-bootstrap-components
import plotly.express as px
import pandas as pd                                        # pip install pandas
from urllib.request import Request, urlopen
from dotenv import dotenv_values                           # pip install python-dotenv
import json


# get eth-to-usd dataset
df_eth_usd = pd.read_csv("https://raw.githubusercontent.com/Coding-with-Adam/Dash-by-Plotly/master/Analytic_Web_Apps/Blockchain-minimal/Gemini_ETHUSD_d.csv")
df_eth_usd['date'] = pd.to_datetime(df_eth_usd['date'])

# get eth-addresses dataset
df_eth_addr = pd.read_csv("https://raw.githubusercontent.com/Coding-with-Adam/Dash-by-Plotly/master/Analytic_Web_Apps/Blockchain-minimal/DailyActiveEthAddress.csv")
df_eth_addr['date'] = pd.to_datetime(df_eth_addr['date'])

# set up beaconchain api key for data on gas prices
config = dotenv_values(".env")
api_key = config['API_KEY']
# your .env file should have this line: API_KEY = "your-beaconchain-api-key"

# function to build one card for each gas price category
def make_card(key, get_data):
    return dbc.Card(
        [
            dbc.CardHeader(html.H2(key)),
            dbc.CardBody([
                html.H3(
                    f"{int(get_data[key] / 1000000000)} GWei",
                    id=key),
            ])
        ], className="text-center shadow")


# display app components on page
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = dbc.Container([
    html.H1("Live Gas Prices", style={'textAlign': 'center'}),
    dbc.Row(children=[], id='gas-data-display',className="my-4"),
    dbc.Row([
        dbc.Col([
            html.H3("Eth Value"),
            dcc.Dropdown(options=df_eth_usd.columns[3:], value='open', clearable=False, id='col_price'),
            dcc.Graph(figure={}, id='eth_usd_graph')
        ], width=6),
        dbc.Col([
            html.H3("Active Ethereum Addresses"),
            dcc.Dropdown(options=df_eth_addr.columns[1:], value='Unique Address Total Count', clearable=False, id='col_addr'),
            dcc.Graph(figure={}, id='eth_addr_graph')
        ], width=6)
    ]),
    dcc.Interval(id='update_trigger', interval=1000*4) # trigger every 4 seconds
])

# build the graphs based on dropdown value selected
@callback(
    Output(component_id='eth_usd_graph', component_property='figure'),
    Output('eth_addr_graph', component_property='figure'),
    Input('col_price', component_property='value'),
    Input('col_addr', component_property='value')
)
def udpate_graph(col_p_selected, col_a_selected):
    price_fig = px.line(data_frame=df_eth_usd, x='date', y=col_p_selected)
    addr_fig = px.line(data_frame=df_eth_addr, x='date', y=col_a_selected)
    return price_fig, addr_fig


# interval component triggers the callback to pull the current gas prices
@callback(
    Output('gas-data-display','children'),
    Input('update_trigger','n_intervals')
)
def udpate_gas_price(_):
    gas_price = {"code":200,"data":{"rapid":31701870016,"fast":24753659720,"standard":24753659720,"slow":24753659720}}

    # req = Request(
    #     url=f'https://beaconcha.in/api/v1/execution/gasnow?apikey={api_key}',
    #     headers={'User-Agent': 'Mozilla/5.0'}
    # )
    # web_byte = urlopen(req).read()
    # gas_price_string = web_byte.decode('utf-8')
    # gas_price = json.loads(gas_price_string)  # convert string to dict
    # gas_price["data"].pop("timestamp")
    # gas_price["data"].pop("priceUSD")
    # print(gas_price)
    
    gas_cards = [dbc.Col(make_card(y, gas_price["data"])) for y in gas_price["data"]]
    return gas_cards


if __name__ == '__main__':
    app.run(debug=True)

Wow, just a few lines of code to build a beautiful dashboard app in the blockchain space! πŸ€―πŸ§‘β€πŸ’»

Here’s a step-by-step explanation:

  1. Import necessary libraries.
    • Dash is a productive Python framework for building web applications.
    • dash_bootstrap_components is a library for adding Bootstrap components to your Dash apps.
    • plotly.express is a simple syntax for complex charts.
    • pandas is a data manipulation and analysis library.
    • urllib.request is used to open URLs.
    • dotenv is used to pull the API key from a local .env file.
    • json is used to parse JSON formatted data.
  2. Get and process the eth-to-usd dataset from a GitHub repository, changing the 'date' column to a datetime format. The same is done for the eth-addresses dataset.
  3. Load the API key for beaconchain from a .env file, which is used to fetch Ethereum’s gas prices.
  4. Define a function make_card(key, get_data). This function will build a Bootstrap card for each gas price category.
  5. Set up the Dash application and define the layout of the app.
    • The layout is a Bootstrap container that includes a heading, rows of Bootstrap cards, and two columns each containing a dropdown and a graph. The dropdowns are populated with column headers from the two datasets.
    • The dcc.Interval component is used to trigger an update function every 4 seconds.
  6. Define a callback function udpate_graph(col_p_selected, col_a_selected). This function takes as input the selected values from the two dropdowns, uses those to select columns from the two dataframes, and returns line charts of those columns.
  7. Define another callback function udpate_gas_price(_). This function is triggered every time the Interval component completes a cycle (every 4 seconds). This function fetches the current gas prices, builds Bootstrap cards with these prices, and returns these cards as a list of columns to be displayed in the 'gas-data-display' row. The actual API request is commented out, so the function currently uses hardcoded data.
  8. Finally, if the script is run directly (as opposed to being imported as a module), it starts the Dash server with debug mode on. This mode provides detailed error messages, and the server will automatically reload when it detects changes in the source code.

Please note that the code currently uses hardcoded data for gas prices. The commented-out section shows how you could fetch live data from an API using an API key stored in a .env file. To use this live data, you would need to uncomment the relevant section and provide your own API key.

πŸ”— Recommended: Python Plotly Dash Cheat Sheet


If you’re interested in learning more about how to create beautiful dashboard applications in Python, check out our new book Python Dash.

You’ve seen dashboards before; think election result visualizations you can update in real-time, or population maps you can filter by demographic.

With the Python Dash library, you’ll create analytic dashboards that present data in effective, usable, elegant ways in just a few lines of code.

Get the book on NoStarch or Amazon!