Skip to content

nsmithau/xrpl-turbo-flask-demo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Creating a dynamically updating XRP Ledger monitor with Turbo Flask

To begin you may want to create a directory and activate a virtual environment for your project. Once that is done install Flask, Turbo-Flask and the XRP Ledger Python library.

% pip install flask turbo-flask xrpl-py

First create a static Flask web application named app.py that will display basic XRP Ledger (XRPL) data when the client browser make a request:

from flask import Flask, render_template  
from xrpl.clients import JsonRpcClient  
from xrpl.models import Ledger  
  
app = Flask(__name__)  
  
# Create a client to connect to the test network  
client = JsonRpcClient("https://testnet.xrpl-labs.com/")  
  
@app.route('/')  
def index():  
    return render_template('index.html')  
  
@app.context_processor  
def inject_ledger():  
    # Create a Ledger request and have the client call it  
    ledger_request = Ledger(ledger_index="validated", transactions=True)  
    ledger_response = client.request(ledger_request).result  
    ledger = ledger_response['ledger']  
    return {'close_time_human': ledger['close_time_human'],  
            'ledger_hash': ledger['ledger_hash'],  
            'ledger_index': ledger['ledger_index'],  
            'tx_count': str(len(ledger['transactions']))  
            }

The JsonRpcClient class provides a sync client for interacting with the XRP Ledger JSON RPC. The function inject_ledger uses this client to request the latest validated ledger from the testnet blockchain, an example of a successful response is shown below:

{  
  "result": {  
    "ledger": {  
      "accepted": true,  
      "account_hash": "B258A8BB4743FB74CBBD6E9F67E4A56C4432EA09E5805E4CC2DA26F2DBE8F3D1",  
      "close_flags": 0,  
      "close_time": 638329271,  
      "close_time_human": "2020-Mar-24 01:41:11.000000000 UTC",  
      "close_time_resolution": 10,  
      "closed": true,  
      "hash": "3652D7FD0576BC452C0D2E9B747BDD733075971D1A9A1D98125055DEF428721A",  
      "ledger_hash": "3652D7FD0576BC452C0D2E9B747BDD733075971D1A9A1D98125055DEF428721A",  
      "ledger_index": "54300940",  
      "parent_close_time": 638329270,  
      "parent_hash": "AE996778246BC81F85D5AF051241DAA577C23BCA04C034A7074F93700194520D",  
      "seqNum": "54300940",  
      "totalCoins": "99991024049618156",  
      "total_coins": "99991024049618156",  
      "transaction_hash": "FC6FFCB71B2527DDD630EE5409D38913B4D4C026AA6C3B14A3E9D4ED45CFE30D"  
    },  
    "ledger_hash": "3652D7FD0576BC452C0D2E9B747BDD733075971D1A9A1D98125055DEF428721A",  
    "ledger_index": 54300940,  
    "status": "success",  
    "validated": true  
  }  
}

Flask’s context_processor decorator makes our inject_ledger function available to the Flask application.

Inside the project create a folder called templates which contains html files to be served by the Flask development server on runtime:

my-app/  
├─ templates/  
│  ├─ base.html  
│  ├─ index.html  
│  ├─ ledger.html  
├─ app.py

The base.html includes the HTML definition and simple style for the table that will contain data retrieved from the XRPL by our application:

<!doctype html>  
<html>  
  <head>  
    <title>XRP Ledger + Turbo Flask Demo</title>  
    <style>  
      .ledger {  
        float: left;  
        width: 780px;  
        border: 1px solid black;  
        margin-right: 10px;  
        margin-bottom: 10px;  
        padding: 10px;  
      }  
      .ledger th, .ledger td {  
        padding: 6px;  
        text-align: left;  
      }  
    </style>  
  </head>  
  <body>  
    {% block content %}{% endblock %}  
    {% include "ledger.html" %}  
  </body>  
</html>

The index.html served by Flask extends the base template and simply includes some introductory text:

{% extends "base.html" %}{% block content %}  
<h1>The XRP Ledger: The Blockchain Built for Business</h1>  
<p>The XRP Ledger (XRPL) is a decentralized, public blockchain led by a global community of businesses and developers looking to solve problems and create value.</p>  
<p>Visit <a href="[https://xrpl.org/](https://xrpl.org/)" target="_blank">xrpl.log</a> to learn more.</p>  
{% endblock %}

Finally ledger.html includes the Jinja template variables to be populated by the inject_ledger function inside our application:

<p>  
    <div id="ledger" class="ledger">  
        <table>  
          <tr><th>Close Time: </th><td>{{ close_time_human }}</td></tr>  
          <tr><th>Ledger Hash: </th><td>{{ ledger_hash }}</td></tr>  
          <tr><th>Ledger Index: </th><td><a href="//testnet.xrpl.org/ledgers/{{ ledger_index }}" target="_blank">{{ledger_index }}</a></td></tr>  
          <tr><th># of TXs: </th><td>{{ tx_count }}</td></tr>  
        </table>  
    </div>  
</p>

Now run the application and open a browser to the Flask development web server running on http://127.0.0.1:5000

% flask run

Note the page is static, data is updated only when the user presses refresh. To make this page dynamic we introduce the magic of Hotwire’s 🌶 Turbo

Import the Turbo class and immediately after the Flask application instance is initialised wire it up to Turbo:

from turbo_flask import Turbo
turbo = Turbo(app)

Import threading and time for a new background process:

import threading  
import time

At the bottom of your app.py file create the new background process which uses Turbo to push updates into the ledger.html file every 5 seconds. Setting daemon=True inside our thread will ensure the process stops when the main Flask application exits:

def update_ledger():  
    with app.app_context():  
        while True:  
            time.sleep(5)  
            turbo.push(turbo.replace(render_template('ledger.html'), 'ledger'))  
  
with app.app_context():  
    threading.Thread(target=update_ledger,daemon=True).start()

Inside the base.html include Turbo inside the <head> element. This opens a websocket connection with the web server allowing the server to send data to the client without them having to request it:

<!doctype html>  
<html>  
 <head>  
 …  
 {{ turbo() }}  
 </head>  
</html>

Run the Flask (now with Turbo) application:

% flask run

Open your browser to http://127.0.0.1:5000 and watch as the background process dynamically updates information from the XRP Ledger without refreshing the page as shown in this animated gif:

References:

[1] Dynamically Update Your Flask Web Pages Using Turbo-Flask
[2] XRPL Code Snippets
[3] Flask deprecated before_first_request how to update
[4] Flask v2.3.x Release Notes
[5] Threading — Thread Objects

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published