Fetching and Displaying Blockchain Data with Koios API
added: September 8, 2023
LINKS:
Let's build a simple website that displays current Stake Pools securing Cardano network. While the website may appear simple, it is designed to introduce you to fundamental concepts vital for future projects. Learning to interact with the Cardano API through a backend is a crucial skill when developing most dApps. Although Next.js is a prevalent framework in today's web development landscape, we'll be using Flask for this project. Flask's lightweight nature makes it considerably easier to grasp how things work, offering a more beginner-friendly approach.
Initial Setup
Download Python installation package for your OS and simply follow the setup process. Onced installed you can doulbe check if python is up and running on your machine by going to terminal and executing: python --version If you or a Mac or Linux you might use: python3 --version
To enable our application to make API calls, we need to install the appropriate library for Flask. To do this, use the pip3 install requests command in the terminal.
For our Flask app, using Render.com provides a quick and convenient way to deploy and host the application on the cloud, making it accessible to users around the world without the need to manage our own servers.
application structure
Folder Structure will be as follows:
├── static
│ └── style.css
├── templates
│ └── index.html
└── app.py
gitignore
requirements.txt
procfile
index.html - serves as the frontend template for our web app
app.py - our Flask app logic, including routes and API calls
style.css - contains all the CSS styles
requirements.txt - lists all the Python packages required for our Flask app to run
Procfile - instructs the server to use Gunicorn as the WSGI HTTP Server
.gitignore - tells Git which files and directories to ignore when pushing to a repository
coding our web app
index.html frontend - In this step, we'll create our HTML template, which will serve as the display platform for our data. We'll present the data in the form of a two column table. One column for PoolID and the other for Pool Ticker. Please note that, for now, it's simply a placeholder. We'll revisit this later when we incorporate data from the backend - app.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="static/style.css">
<title>STAKE POOL LIST</title>
</head>
<body>
<h1>CARDANO STAKE POOLS</h1>
<table>
<thead>
<tr>
<th>Pool ID (Bech32)</th>
<th>Ticker</th>
</tr>
</thead>
<tbody>
<tr>
<td>pool_ID-placeholder</td>
<td>pool_Ticker-placeholder</td>
</tr>
</tbody>
</table>
</body>
</html>
app.py backend - this code creates a Flask web application that defines a single route ('/') and sends an HTTP GET request to an external API to retrieve JSON data. If the request is successful (status code 200), it parses the JSON data and renders an HTML template index.html while passing the retrieved data to be displayed in the template.
from flask import Flask, render_template
import requests
app = Flask(__name__)
@app.route('/')
def index():
url = "https://api.koios.rest/api/v0/pool_list"
headers = {"accept": "application/json"}
response = requests.get(url, headers=headers)
if response.status_code == 200:
pool_list = response.json()
else:
pool_list = None
return render_template('index.html', pool_list=pool_list)
if __name__ == '__main__':
app.run()
With our backend code all set up, it's time to pass the data to our index.html file. We'll integrate it with Flask to dynamically create a webpage that showcases the list of Cardano Stake Pools.
index.html code should look like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="static/style.css">
<title>STAKE POOL LIST</title>
</head>
<body>
<div class="wrapper">
<h1>CARDANO STAKE POOLS</h1>
{% if pool_list %}
<table>
<thead>
<tr>
<th>Pool ID (Bech32)</th>
<th>Ticker</th>
</tr>
</thead>
<tbody>
{% for pool in pool_list %}
<tr>
<td>{{ pool.pool_id_bech32 }}</td>
<td>{{ pool.ticker }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>No data available.</p>
{% endif %}
</div>
</body>
</html>
Let's test the app on your local machine to ensure it's functioning correctly. Open your terminal and navigate to the folder containing your app.py file. Then, simply execute the command python app.py to run the application. You can access the application by entering http://127.0.0.1:5000 in your web browser; this URL corresponds to the local host.
The app is functional! Currently, you can view the list of stake pools that secure the Cardano Network on your website; however, there is a minor caveat — it is only available to you locally. Before we deploy it to a cloud server, let's edit the index.html one last time to include a link to cardanoscan replacing the plain text. Note that we cannot link to pool.pm, as linking to a specific pool on pool.pm requires hex decoding, which we currently do not have, as opposed to the Bech32 format we are receiving from KOIOS API now.
To link each pool to cardanoscan, we need to construct a URL that follows this pattern: https://cardanoscan.io/pool/pool_id_bech32, where pool_id_bech32 corresponds to the individual Bech32 ID we receive for each pool from the KOIOS API. To do this, we simply need to edit our td tag in the index.html file:
<td><a href="https://cardanoscan.io/pool/{{ pool.pool_id_bech32 }}">{{ pool.pool_id_bech32 }}</a></td>
style.css - lastly, let's simply style our website:
@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@100;300;400;700&display=swap');
*{
margin: 0;
padding: 0;
box-sizing: border-box;
scroll-padding-top: 80px;
}
html, body{
width: 100%;
height: 100%;
font-family: 'Roboto Mono', monospace;
background-color: #1a1a1a;
color: white;
text-transform: uppercase;
}
img,
picture,
svg,
video,
canvas {
max-width: 100%;
display: block;
}
a{
color: #6b947c;
}
a:hover{
color: #7da58e;
}
h1{
padding: 50px 0;
font-family: 'Roboto Mono', monospace;
}
.wrapper{
width: 1000px;
margin: 0 auto;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid #343434;
padding: 8px;
text-align: left;
}
The final result:
deployment to render.com
There are a few steps here, but most of them you only need to do once per app. You will have to update requirements.txt file when you add more packages to your application but after you push these changes to GitHub, Render will automatically build the app.
The Procfile instructs Render to initiate a process named web and to execute the command python app.py, effectively launching our web app.
Before we create our Procfile, we will install one last package called Gunicorn.
This is a simple text file that contains a list of all the modules and packages required for your project. Remember when we installed Flask? Or Requests? And, most recently, Gunicorn? These are all Python packages that our app uses. This file simply informs the cloud server of these dependencies so it can install them while building the app.
Flask==2.3.2
gunicorn==21.2.0
Jinja2==3.1.2
requests==2.31.0
To deploy our web app to the cloud, the first step is to create a repository on GitHub where we can store our web app's source code. This process is straightforward, even if you're new to GitHub, as there are numerous resources available on YouTube for guidance.
Here are some YT tutorials that you could be helpful:
- Using Git with Visual Studio Code
- How To Use GitHub with VS Code
You can check it out using the domain Render gave you. And guess what? You can even set up your very own custom domain down the road. But for now, that's all there is to it!
final notes
Building a basic website to showcase Cardano network Stake Pools is a fundamental exercise in blockchain API interaction. It's a great starting point for expanding your project. You can enhance it by integrating more features, such as exploring the KOIOS API for additional data. After making changes, test locally and then push to GitHub; Render will automatically update your website when it detects changes.