Loading proofofbrain-blog...

Hive Authentication Client (HAC)

hive_auth_client_hac.jpg

As I got some free time lately I decided to use it for the HIVE community either in publishing open source tools for application developers on HIVE or for personal & professional projects on HIVE.

After the HIVE Nodes Checker it's time to introduce the Hive Authentication Client (HAC)

Hive Authentication Client (HAC)

Hive Authentication Client (HAC) is a password-less users authentication, sign and broadcast transactions for the HIVE Blockchain through the Hive Authentication Services (HAS) or the Hive Keychain Browser Extension (KBE).

Authentications and transactions are performed by the wallet supporting the HAS protocol or the Hive Keychain Browser Extension without communicating the private key, which thus remains secure. The results of each operation are sent by subscription (RxJS).

Hive Authentication Client (HAC) manages previous connections as well through encrypted data in the localStorage.

In order to save time on the learning curve of the HIVE blockchain, some operations exist in short versions too (e.g. hacFollowing, hacTransfer, hacDelegation...).

Big thank to @arcange who is the originator of the Hive Authentication Services (HAS) and to @stoodkev for his work to make the HIVE Keychain wallet compatible with the HAS protocol 👍

Hive Authentication Services (HAS)

Manage the WebSocket connection to the HAS and all communication with it. Support reconnection to another HAS WebSocket server in case of failure.

HAS documentation: https://docs.hiveauth.com/

Hive Keychain Browser Extension (KBE)

Manage the communication with the Hive Keychain Browser Extension if present

KBE documentation: https://github.com/stoodkev/hive-keychain

Github & NPM

Like the Hive Authentication Services (HAS) this package remains in BETA!

screenshot_2022_01_20_031705.jpg

Use case example (extremely basic)

I propose to show you how the Hive Authentication Client (HAC) works through a short Angular app example, which will be more meaningful.

Our application will allow us to connect to the HIVE blockchain via HAS or KBE and to proceed to some transactions like Upvote for witness and Follow/Unfollow.

For a more complete example, you can go there :
https://github.com/Mintrawa/hac-tutorial

Angular example

Initialize

create a new angular project

$  ng new hac-tutorial

choose yes for routing option and, CSS or SCSS.

Install the dependencies we will need for this tutorial

~/hac-tutorial$  npm i --save ng-qrcode @mintrawa/hive-auth-client

Edit

open the project directory with your favorite editor

angular.json

Due to the usage of CommonJS dependencies, we need to add a section allowedCommonJsDependencies in our angular.json file after "scripts": [],.

"allowedCommonJsDependencies": [
   "@mintrawa/hive-auth-client",
   "qrcode"
]

app.module.ts

For the tutorial, we will need to show a QRcode, to do this we will use the ng-qrcode package

Open the app.module.ts and add the import line import { QrCodeModule } from 'ng-qrcode'; and in the import array add QrCodeModule,

app.component.ts

In this example, we will do everything from the app.component.ts

import { Component, OnDestroy, OnInit } from '@angular/core';

/** Hive Authentication Client (HAC) */
import {
  HiveAuthClient,
  hacMsg,
  hacUserAuth,
  hacFollowing,
  hacWitnessVote,
} from '@mintrawa/hive-auth-client';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit, OnDestroy {
  loader = false;
  voteWitnessLoader = false;
  voteWitnessButton = false;
  followLoader = false;
  followButton = false;
  qrHAS: string | undefined;
  username?: string;
  connected?: string;
  pwd = '520c5c9b-bd58-4253-850a-1fa591a2dabd';

  connect(username: string): void {
    this.loader = true;
    this.username = username;
    hacUserAuth(username, { name: 'HACtutorial' }, this.pwd, {
      key_type: 'active',
      value: 'MyCha11en6e',
    });
  }

  voteWitness(witness: string, approve: boolean): void {
    this.voteWitnessLoader = true;
    this.followButton = true;
    hacWitnessVote(witness, approve);
  }

  follow(account: string, follow: boolean): void {
    this.followLoader = true;
    this.voteWitnessButton = true;
    hacFollowing(account, follow);
  }

  ngOnInit(): void {
    /** Initialize the HIVE auth client */
    HiveAuthClient();

    hacMsg.subscribe((m) => {
      console.log(m);

      /** Received auth_wait => generate the qrCode */
      if (m.type === 'qr_code') {
        /** QRcode data */
        this.qrHAS = (m as any).msg;
      }

      /** Received authentication msg */
      if (m.type === 'authentication') {
        if (!m.error) {
          this.connected = m.msg?.data?.chalenge.slice(0, 12) + '...';
        } else {
          this.loader = false;
          this.qrHAS = null;
          window.alert(`${m.error.msg}`);
        }
      }

      /** Received sign_result */
      if (m.type === 'tx_result') {
        this.voteWitnessLoader
          ? (this.voteWitnessLoader = false)
          : (this.followLoader = false);
        this.voteWitnessButton
          ? (this.voteWitnessButton = false)
          : (this.followButton = false);
        window.alert(`${m.msg?.status} | ${m.msg?.uuid ? m.msg?.uuid : ''}`);
      }
    });
  }

  ngOnDestroy(): void {
    hacMsg.unsubscribe();
  }
}

app.component.scss

a little touch of style

.flex-container {
  display: flex;
  flex-flow: column wrap;
  justify-content: center;
  align-content: stretch;
  align-items: center;
  height: 100vh;
}

.encart {
  border: 2px solid red;
  padding: 20px;
  border-radius: 25px;
}

.loader {
  border: 4px solid #f3f3f3;
  border-radius: 50%;
  border-top: 4px solid red;
  width: 16px;
  height: 16px;
  -webkit-animation: spin 2s linear infinite; /* Safari */
  animation: spin 2s linear infinite;
}

.operations {
  display: flex;
  flex-flow: column wrap;
  justify-content: center;
  align-content: stretch;
  align-items: flex-start;
  height: 100vh;
  padding: 12px;
}
.item {
  width: 250px;
  height: 80px;
}

app.component.html

Time to do our HTML.

<div class="flex-container">
  
  <div class="encart" *ngIf="!connected && !qrHAS">
    <div>HIVE Username</div>
    <div style="height:6px;"></div>
    <input #username type="text" />
    <div style="height:6px;"></div>
    <button (click)="connect(username.value)" *ngIf="!loader">
      HAS Connect
    </button>
  </div>
  
  <div class="encart" *ngIf="!connected && qrHAS">
    <div>{{ username }}</div>
    <qr-code
      [value]="'has://auth_req/' + qrHAS"
      [size]="192"
      [errorCorrectionLevel]="'M'"
    ></qr-code>
    <div *ngIf="loader" class="loader"></div>
  </div>
  
  <div *ngIf="connected" class="operations">
    
    <div class="encart item">
      <div>VOTE WITNESS</div>
      <div style="height:6px;"></div>
      <div>
        <div>witness: <input #witness type="text" value="mintrawa" />
        <div style="height: 6px;"></div>
        <div *ngIf="!voteWitnessLoader">
          <button
            [disabled]="voteWitnessButton"
            (click)="voteWitness(witness.value, true)"
          >
            APPROVE</button
          >&nbsp;
          <button
            [disabled]="voteWitnessButton"
            (click)="voteWitness(witness.value, false)"
          >
            DISAPPROVE
          </button>
        </div>
        <div class="loader" *ngIf="voteWitnessLoader"></div>
      </div>
    </div>
    <div style="height:12px;"></div>
    
    <div class="encart item">
      <div>FOLLOWING</div>
      <div style="height:6px;"></div>
      <div>
        <div><input #following type="text" value="mintrawa" />
        <div style="height: 6px;"></div>
        <div *ngIf="!followLoader">
          <button
            [disabled]="followButton"
            (click)="follow(following.value, true)"
          >
            FOLLOW</button
          >&nbsp;
          <button
            [disabled]="followButton"
            (click)="follow(following.value, false)"
          >
            UNFOLLOW
          </button>
        </div>
        <div class="loader" *ngIf="followLoader"></div>
      </div>
    </div>
  </div>
</div>

This short example is also available on Stackblitz
https://stackblitz.com/edit/angular-ivy-ew73hs

hac-tutorial

A more complete example is available on Github here:
https://github.com/Mintrawa/hac-tutorial

  • Mode debug
  • Fallback on the first HAS server
  • Management previous connections
  • Choice between HAS or Keychain
  • 1 page for the sign in and 1 for the operations
  • 8 operations in easy mode
    • follow/unfollow
    • vote/downvote
    • approve/disapprove Witness
    • transfer
    • transferToVesting
    • withdrawVesting
    • delegation
    • convert (HBD=>HIVE / HIVE=>HBD)
  • 1 manual operation (claim discount account)

Original photo by olieman.eth on Unsplash


My HIVE witness servers

PRINCIPAL
BACKUP/SEED
CPU:Intel Xeon E3-1270v6CPU: Intel Xeon E3-1230v6
4 Cores/8 Threads 3.5 GHz/3.9 GHz4 Cores/8 Threads 3.8 GHz/4.2 GHz
RAM: 32GB DDR4 ECC 2133MHzRAM: 32GB DDR4 ECC 2133MHz
HDD: 1 To SSD NVMeHDD: 1 To SSD NVMe


Vote for my HIVE witness: click here (via HiveSigner)

H2
H3
H4
3 columns
2 columns
1 column
28 Comments