Shankar Nathan

@shankqr

How to build a simple Front End for your EOS smart contract

December 29th 2018

We are going to build a simple Front End that interacts with an EOS smart contract

Our simple front end: Login Page

I have always been a big fan of React from the very beginning, but lately I have been playing around with Vue and have to admit that I really fell in love with it for it’s simplicity. To keep things simple as possible for you, I have decided to use Vue to build our front end this time.

NOTE: If you have not tried out Vue, their official documentation is the best place to start.

Create a Vue Project

Start by installing Vue, open up terminal and type this:

npm i -g @vue/cli

Now that Vue is installed we are going to use it’s CLI to create our project

vue create eos-login

When prompted choose “Manually select features” then, use the space bar to select Babel, Router and Vuex feature. For the rest of the questions you can just choose the defaults.

Once the Vue CLI have created our project, we can change directory into it and add plugins. We are going to add the Vuetify plugin for helping us with the design.

cd eos-login
vue add vuetify

You will be asked a series of questions, just follow my answers like bellow:

vuetify options

Ok lastly we will need to install EOS official javascript library so that we can easily make calls to the EOS blockchain.

npm i eosjs@beta

NOTE: The npm package eosjs@beta is the latest compared to just eosjs

By now you will have a perfect project setup to start coding.

npm run serve

Follow the link on your browser and you should see the default Vue template up and running!

Deploy our Smart Contract

Before we start coding the front end let’s deploy our latest smart contract to the EOS blockchain.

I have written a simple smart contract that has a ‘users’ table and a login method that accepts an EOS account as it’s input. The login method will store the account in the users table if no records already exist for that name. However if there is already a record, it will increment the reward_points by 1 instead. The login also ensures that only valid EOS account can enter.

Let’s go ahead and deploy this contract . I have previously written a step by step guide on how to accomplish this, please click here.

Coding the Front End part

Now that we have our hello contract deployed, we can resume our work on the front end. Open the eos-login project folder in VSCode (or you favourite IDE), we will be adding 4 files to our project:

  1. AppTopBar.vue under the components folder
  2. EosService.js under the eosio folder (create this folder)
  3. Login.vue under the views folder
  4. .env under the project root folder

Add this files to your project. Your project structure should now look like bellow.

Project directory structure

Let’s start by coding the AppTopBar component. In Vue, components can be easily added to pages making it very re-usable. The AppTopBar component is simply a header bar with a title of our application.

<!-- AppTopBar.vue -->
<template>
<span>
<v-toolbar app color="black darken-4" dark>
<v-spacer class="hidden-md-and-up"></v-spacer>
<v-toolbar-title>{{appTitle}}</v-toolbar-title>
</v-toolbar>
</span>
</template>
<script>
export default {
name: 'AppTopBar',
data() {
return {
appTitle: 'My EOS Dapp'
};
}
};
</script>
<style scoped>
</style>

Now open App.vue under the src folder to import our component. Notice that AppTopBar has been format as <app-top-bar> inside the template.

<!-- App.vue -->
<template>
<v-app>
<app-top-bar></app-top-bar>
<v-content transition="slide-x-transition">
<router-view></router-view>
</v-content>
</v-app>
</template>
<script>
import AppTopBar from '@/components/AppTopBar';
export default {
name: 'App',
components: {
AppTopBar
}
};
</script>

For our application we will have 2 main page which is the Login page and the Home page. On the App.vue we are using the Vue Router to link to both pages with the <router-view></router-view> tag. Open the router.js file to edit the paths.

//router.js
import Vue from 'vue';
import Router from 'vue-router';
import Login from './views/Login.vue';
Vue.use(Router);
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'login',
component: Login
},
{
path: '/home',
name: 'home',
component: () => import('./views/Home.vue')
}
]
});

Edit our Home.vue

<!-- Home.vue -->
<template>
<v-card-title primary-title>
<h4>Welcome to my Dapp main page!</h4>
</v-card-title>
</template>
<script>
export default {
components: {}
};
</script>

Create our Login.vue

<!-- Login.vue -->
<template>
<v-container>
<v-layout row class="text-xs-center">
<v-flex xs3 style="background-image: url('http://cdn.wallpapersafari.com/7/86/gqiGH7.jpg')">
<v-card height="500px"></v-card>
</v-flex>
<v-flex xs4 class="grey lighten-4">
<v-container style="position: relative;top: 13%;" class="text-xs-center">
<v-card flat>
<v-card-title primary-title>
<h4>Login</h4>
</v-card-title>
<v-form>
<v-text-field
v-model="accountName"
prepend-icon="person"
name="AccountName"
label="Account Name"
></v-text-field>
<v-text-field
v-model="privateKey"
prepend-icon="lock"
name="PrivateKey"
label="Private Key"
></v-text-field>
<v-card-actions>
<v-btn @click="handleLogin()" primary large block>Login</v-btn>
</v-card-actions>
</v-form>
</v-card>
</v-container>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
import EosService from '@/eosio/EosService';
export default {
data() {
return {
accountName: '',
privateKey: ''
};
},
methods: {
handleLogin: function() {
EosService.login(this.accountName, this.privateKey)
.then(() => {
this.$router.push('home');
})
.catch(err => {
alert(err.toString());
});
}
}
};
</script>

The Login.vue page calls the login function on EosService and passes the inputs for account name and private key. If the login function returns success it simply redirects to the Home.vue page.

Now before I dive into the EosService login function, let’s edit our .env file with the correct values. Open the .env file under the project root directory.

VUE_APP_SMART_CONTRACT_NAME="youraccname1"
VUE_APP_NODE_ENDPOINT="https://api.kylin.alohaeos.com:443"

Set the value for VUE_APP_SMART_CONTRACT_NAME to the account name you created earlier on the Testnet to deploy the hello contract. The value for VUE_APP_NODE_ENDPOINT should be then set to a Testnet endpoint, in this case I am using the CryptoKylin Testnet. Subsequently if you have deployed your smart contract on the Mainnet then you should set the value of the endpoint to any of the 21 main block-producers.

EosService

Finally let’s look into the code for the EosService.js library I created. This is where the bulk of action is happening.

//EosService.js
import { Api, JsonRpc } from 'eosjs';
import JsSignatureProvider from 'eosjs/dist/eosjs-jssig';
async function invokeAction(action, dataValue) {
const rpc = new JsonRpc(process.env.VUE_APP_NODE_ENDPOINT);
const privateKey = localStorage.getItem('private_key');
const signatureProvider = new JsSignatureProvider([privateKey]);
const api = new Api({
rpc,
signatureProvider,
textDecoder: new TextDecoder(),
textEncoder: new TextEncoder()
});
try {
const resultWithConfig = await api.transact(
{
actions: [
{
account: process.env.VUE_APP_SMART_CONTRACT_NAME,
name: action,
authorization: [
{
actor: localStorage.getItem('name_account'),
permission: 'active'
}
],
data: dataValue
}
]
},
{
blocksBehind: 3,
expireSeconds: 30
}
);
return resultWithConfig;
} catch (err) {
throw err;
}
}
class EosService {
static login(acc, key) {
return new Promise((resolve, reject) => {
localStorage.setItem('name_account', acc);
localStorage.setItem('private_key', key);
invokeAction('login', { user: acc })
.then(() => {
resolve();
})
.catch(err => {
localStorage.removeItem('name_account');
localStorage.removeItem('private_key');
reject(err);
});
});
}
}
export default EosService;

Basically what we are doing here is creating an API transaction by passing in the parameters of the .env file earlier. For this to work we need to create a signature provider with an EOS account private-key to access the smart contract. Since this is meant to be a simple tutorial we are directly dealing with the private-key here, however in a real world application it is best to integrate with a 3rd party wallet to handle the creation of the signature provider. That way you do not have to ask your users for their private-key directly which is insecure.

NOTE: Scatter is a good example of a 3rd party wallet out there. They have established them-self as one of the trusted wallet solution through out the EOS community. Interestingly they already have an existing API for you to integrate with your applications.

Ok we are done with all the front end code. If you have reached to this point, give yourself a big pat on the back for following through. I believe we have completed a bare minimum front end for any EOS smart contract. All the work you will be doing in the future will most probably be built upon this base.

I have posted this project files on GitHub: https://github.com/shankqr/eos-login . Now will be a good time for you to compare your code and mine to make sure everything is the same before we continue.

Run our Code

Go ahead, get into our project directory and run the code:

npm run serve

Follow the link on your browser: http://localhost:8080/, your screen should look like this:

Enter the details

Enter your account name along with the private key that you have created previously on the Testnet. Click on Login.

Dapp main page

If you have entered everything properly you will be directed to our Home page after a few seconds.

Congratulations! you have just built your first Dapp.

Before we end this series, let us just check to see if our smart contract have registered this login into our users table.

As you can see the return that your record has been added to the users table. Now let’s test to see if the reward_points is incremented if we login again. Refresh your browser and try to login again. After login, let’s check again:

Fantastic! Our smart contract is doing what it was programmed to do. Don’t you just love the Blockchain, it is just so reliable.

Summary

You have learned how to:

  1. Create an empty Vue project
  2. Add a Vue plugin
  3. Install the EOS official javascript library
  4. Write an EOS smart contract that can store data in tables
  5. Connect a front end to EOS

I hope you enjoyed this guide, please leave your comments bellow. I am thinking about writing on Scatter wallet integration next. I would love to hear your thoughts.

Follow me on LinkedIn!

More by Shankar Nathan

More Related Stories