How to build a sports prediction application on the steem blockchain using Node/ExpressJS

in #utopian-io5 years ago (edited)

Repository

https://github.com/nodejs/node

What Will I Learn?

This post marks the beginning of a series of tutorials on how you can build a prediction app that allows users to predict the outcome of sport events and post their predictions on the steem blockchain.

The application we'll be building will have the following features.

  • Users will be able to login using their steem account credentials.

  • A page for creating prediction tickets

  • User dashboard for viewing prediction tickets by the user and other users

  • Steem Wallet that allows users to transfer funds

  • User Profile Page

By the end end of this tutorial we would have covered the user authentication part of the application.

Requirements

In order to be able to follow this tutorial the user has to be able to use the following

  • HTML/CSS
  • JavaScript/JQuery
  • TheSportsDB public api
  • AxiosJS
  • NodeJS/Express
  • SteemJS Api

Difficulty

Intermediate

Tutorial Content

In this post, we'll be adding the user authentication page

By the end of this post, users will be able to login to the application using their steem account details.

I am not going to cover how to setup an express application as this tutorial is not for that purpose.

However, I used express-generator to setup my environment. For a detailed explanation on how you can use express-generator to setup your environment check out ExpressJS's official website.

After everything is set up and the server is running on the default port 3000 as shown in the console

steempredict-1.PNG

You can navigate to http://localhost:3000/ in your browser to confirm the server is working correctly, you should see an interface like below

steempredict-2.PNG

We'll be using jQuery, HTMLandCSS` for the front end components.

Steem User Authentication

Before a user can create a ticket and post it on the steem blockchain the user has to login first using their steem credentials.

To start with, in your project directory create a sub-directory client and in the new folder add another file login.html.

In the same folder add the following sub directories js, for JavaScript files, and css for CSS styles.

In the js folder add a file login.js and in the cssdirectory add a file login.css.

In login.html and login.css add the following code to display the login form

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Login To SteemPredict</title>
    <link rel="stylesheet" href="./css/login.css">
</head>
<body>
    <div class="login-page">
        <div class="form">
          <form class="login-form">
            <input type="text" placeholder="username"  class="username"/>
            <input type="password" placeholder="password"  class="password"/>
            <a class="login-btn" onclick="login()">login</a>
          </form>
        </div>
      </div>

    <script src="https://code.jquery.com/jquery-3.4.1.js"></script>
    <script src="./js/login.js"></script>
</body>
</html>

login.css

@import url(https://fonts.googleapis.com/css?family=Roboto:300);

.login-page {
  width: 360px;
  padding: 8% 0 0;
  margin: auto;
}
.form {
  position: relative;
  z-index: 1;
  background: #FFFFFF;
  max-width: 360px;
  margin: 0 auto 100px;
  padding: 45px;
  text-align: center;
  box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
}
.form input {
  font-family: "Roboto", sans-serif;
  outline: 0;
  background: #f2f2f2;
  width: 100%;
  border: 0;
  margin: 0 0 15px;
  padding: 15px;
  box-sizing: border-box;
  font-size: 14px;
}
.form button {
  font-family: "Roboto", sans-serif;
  text-transform: uppercase;
  outline: 0;
  background: rgb(46, 46, 45);
  width: 100%;
  border: 0;
  padding: 15px;
  color: #FFFFFF;
  font-size: 14px;
  -webkit-transition: all 0.3 ease;
  transition: all 0.3 ease;
  cursor: pointer;
}
.form button:hover,.form button:active,.form button:focus {
  background: rgb(46, 46, 45);
}
.form .message {
  margin: 15px 0 0;
  color: #b3b3b3;
  font-size: 12px;
}
.form .message a {
  color: #4CAF50;
  text-decoration: none;
}
.form .register-form {
  display: none;
}
.container {
  position: relative;
  z-index: 1;
  max-width: 300px;
  margin: 0 auto;
}
.container:before, .container:after {
  content: "";
  display: block;
  clear: both;
}
.container .info {
  margin: 50px auto;
  text-align: center;
}
.container .info h1 {
  margin: 0 0 15px;
  padding: 0;
  font-size: 36px;
  font-weight: 300;
  color: #1a1a1a;
}
.container .info span {
  color: #4d4d4d;
  font-size: 12px;
}
.container .info span a {
  color: #000000;
  text-decoration: none;
}
.container .info span .fa {
  color: #EF3B3A;
}
body {
  background: #76b852; /* fallback for old browsers */
  background: -webkit-linear-gradient(right, rgb(46, 46, 45), rgb(46, 46, 45));
  background: -moz-linear-gradient(right, rgb(46, 46, 45), rgb(46, 46, 45));
  background: -o-linear-gradient(right, rgb(46, 46, 45), rgb(46, 46, 45));
  background: linear-gradient(to left, rgb(46, 46, 45), rgb(46, 46, 45));
  font-family: "Roboto", sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;      
}

login.js

$(document).ready(function() {
    $('.message a').click(function(){
        $('form').animate({height: "toggle", opacity: "toggle"}, "slow");
    });
})

If you load login.html in your browser you should have an interface like below

steempredict-3.PNG

After designing the interface, we are going to move on to the authentication part of the application.

Before that however, we need to add some modules to our backend.

We'll be adding the following modules to our backend

  • SteemJS
  • Mongoose

SteemJs will help us handle all api calls to the steem blockchain while Mongoose is a MongoDB helper that will help us create a database driven application.

Open your command line, navigate to your project root directory and run the following code to install both packages.

SteemJS

npm install steem

Mongoose

npm install mongoose

After installing both packages we can now go back to login.js so we can grab the form data in login.html to be used for logging in our steem account.

In login.js, add the following code to grab form data

function login() {
    const username = $('.username').val();
    const password = $('.password').val();

    console.log(username, password);
}

We need to send the form data to the backend for validation and token creation and to do that we need to add AxiosJs to our project.

AxiosJs is used for sending api requests and retrieving data through the request.

In order to use AxiosJs in our application, we need to bring it in through cdn in a scripttag.

Add the following code in login.html

<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.js"></script>

This pulls in axios for use in our application.

After bringing in axios, we will now send a request to the backend to log the user in with their steem account details.

In login.js replace the line console.log(username, password); with the following

 // send request with axios

    axios.post('http://localhost:3000/login', {
        username,
        password
    }).then(response => {
        console.log(response)
    }).catch(err => {
         console.log(err);
    })

Go back to the root directory where the backend files are located and open app.js.

In app.js, below the line app.use('/users', usersRouter); add the following code.

app.post('/login', loginRouter)

Beelow the line var usersRouter = require('./routes/users'); add the code

var loginRouter = require('./routes/login');

We also need to include cors in order to enable Cross Origin Requests.

In the root directory console, run the code npm install cors --save to install `cors for usage.

In app.js, below the line var logger = require('morgan'); add the following code

var cors = require('cors')

On the line after the line var app = express();, add the following code

app.use(cors())

We need to connect our application to the MongoDB database using mongoose, and to do that add the following code again below the line var app = express();.

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/steempredict', { promiseLibrary: require('bluebird') })
  .then(() =>  console.log('connection successful'))
  .catch((err) => console.error(err));

if you save the file and restart the server and also start up your MongoDB server you should get the following in the server console

steempredict-6.PNG

In the routes directory add a new file login.js. In the file add the following code

var express = require('express');
var router = express.Router();
var steem = require('steem');

router.post('/login', function(req, res) {
    console.log(req.body)
})


module.exports = router;

Save all files, restart the server and reload login.html, if you try to log in any user now you should get something like this in your browser console.

steempredict-4.PNG

In order to log the user in using the steem account, replace console.log(req.body) in login.js with the following

const username = req.body.loginParam.username;
    const password = req.body.loginParam.password;

    steem.api.getAccounts([username], function(err, user){
        // store postinq wif in variable

        const pubWif = user[0].posting.key_auths[0][0];

        // check for the validity of the posting key

        if(steem.auth.isWif(password)){
            // check if the public key tallies with the private key provided

            const Valid = steem.auth.wifIsValid(password, pubWif);

            if(Valid){
                console.log("true"); 
            } else {
                console.log("false");
            }
        }
    });

Save all files, restart server and reload ;login.html, if you try to login with your steem username and posting key, you should get a result like the image in the console below

steempredict-5.PNG

Getting the value true in the console means that the user credentials has been validated successfully.

At this point we have to send a response back to the client and our response will include the following details

  • A boolean value true indicating successful login

  • A signed session token, courtesy of json web token which we'll be installing in a bit.

  • The user details of the logged in account

In order to install json web token run the following command in the project root directory console

npm install jsonwebtoken

After the line var steem = require('steem'); add the code var jwt = require('jsonwebtoken');

We need a config file that can store our session secret and other configurations.

In the root directory, create a new file config.js and add the following code

module.exports = {
    'secret': 'ADD YOUR SECRET HERE'
}

Bring the file into login.js by adding the following code below the line var jwt = require('jsonwebtoken');

var config = require('../config');

In login.js, replace the line console.log(true) with the following code

// create token and store in token variable

                var token = jwt.sign({ id: user._id }, config.secret, {
                    expiresIn: 86400
                });

                // if user authentication is successful send auth confirmation, token and user data as response

                res.json({
                    auth: true,
                    token: token,
                    user: user
                });

If you save the files, restart the server and try to login you should get an identical response to the image below in your browser console, provided login is successful.

steempredict-7.PNG

The image above signifies successful login. To be continued.

Proof of Work Done

https://github.com/olatundeee/steempredict

Sort:  

Thank you for your contribution @gotgame.
After analyzing your tutorial we suggest the following points below:

  • Your code isn't indent. It's very important to have the code lines ident so readers can understand what you are developing.

  • It isn't necessary to put the CSS code lines in your tutorial.

  • It would be interesting to have some gifs with the demonstration of what you have developed for this tutorial.

Thank you for your work in developing this tutorial.
Looking forward to your upcoming tutorials.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Chat with us on Discord.

[utopian-moderator]

Thank you for your review, @portugalcoin! Keep up the good work!

Hi, @gotgame!

You just got a 0.21% upvote from SteemPlus!
To get higher upvotes, earn more SteemPlus Points (SPP). On your Steemit wallet, check your SPP balance and click on "How to earn SPP?" to find out all the ways to earn.
If you're not using SteemPlus yet, please check our last posts in here to see the many ways in which SteemPlus can improve your Steem experience on Steemit and Busy.

Hi @gotgame!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server

Hey, @gotgame!

Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

Coin Marketplace

STEEM 0.28
TRX 0.12
JST 0.033
BTC 69488.13
ETH 3501.35
USDT 1.00
SBD 3.69