#2 Ethereum DApp Tutorial: ReactJS + Smart Contracty

V minulej časti sme si vysvetlili čo to vlastne SC(smart contract) je, spustili sme si dev prostredie, rozbehali všetky potrebné veci, otestovali SC a vieme že beží bezchybne. Teraz prišiel čas dať nášmu SC UI(user interface – užívateľské prostredie), čiže z neho vytvoríme reálnu DAppku. Zatiaľ veľmi jednoduchú, ale pre tutoriál a úvod do úvodu to úplne stačí.

Ak ste tu prvý krát a neviete o čo sa jedná, určite si najprv prejdite prvú časť tutoriálu:

#1 Ethereum DApp Tutorial: Intro do Smart Contractov

SC otvorili dvere do úplne nového sveta tvorby aplikácií, technologických riešení a návrhu softwaru. SC si každý môže napísať samozrejme sám a reálne ich použiť aj bez potreby UI nadstavby, no extrémne málo ľudí to v súčasnosti dokáže, preto sa tvoria užívateľsky prívetivé dizajny aplikácií ktoré dokážu operovať s SC.

Pre tento turoriál som zvolil React. React je Javascriptová knižnica/framework ktorej hlavné výhody(momentálne pre nás) sú, že je veľmi jednoduchý a postavený na koncepte functional programmingu vďaka čomu je kód racionálnejší a jednoduchší a zároveň je extrémne rýchly. Zaujimavosťou Reactu je, že dokáže ukladať stavy jednotlivých komponentov čo umožňuje “updatovať” informácie na webe bez potreby jeho opetovného načítania(veľmi jednoducho povedané) čo sa pre blockchain DAppky dokonale hodí.

React moc vysvetľovať nechcem aby sme neubehli od pointy ktorou sú SC. Začneme hneď inštaláciou Reactu, inicializáciou react appky a inštaláciou knižnice Web3.

Vďaka React komunite máme k dispozícií úžasnú vec. Jediným príkazom nainštalujeme základný, funkčný balíček reactu bez potreby zbytočného rozbiehania a ďalších inštalácií a to je práve Create React App.

Začneme zasa v konzole zadaním príkazu:

npm install -g create-react-app

Po zbehnutí príkazu sa vrátime do zložky kde máme uložený SC z minulého tutoriálu a zasa v jej roote vytvoríme nový priečinok “UI”. Pomocou konzoly sa do tohto priečinku navigujeme a zadáme príkaz:

create-react-app accounts-dapp

Tento príkaz nám vytvoril react appku s názvom accounts-dapp. Po zbehnutí sa zasa navigujeme v konzole do zložky “accounts-dapp” kde spustíme lokálny server pre našu react appku pomocou príkazu:

npm start

Nesmieme zabudnúť, že nám musí bežať aj náš testovací ethereum blockchain. Spustíme ho v novom okne, v roote nášho projektu príkazom:

testrpc

V editore si otvoríme súbor “package.json”. V tomto kroku potrebujeme nainštalovať nástroje ktoré nám pomôžu spojiť sa s EVM a spracovať jeho dáta. Začneme knižnicou “web3”. Web3 je v podstate Javascriptové API (application interface) ktoré sa napája na JSON-RPC protokol ktorý definuje dátovu štruktúru a jeho pravidlá a ako formát využíva JSON formát, čo je pre javascript veľmi friendly a useful. Druhá knižnica ktorú potrebujeme je lodash. Vďaka lodashu sa nám budú lepšie spracovávať dáta prichádzajúce z web3. V podstate uľahčuje prácu s poliami a objektami a samozrejme omnoho viac.

Súbor package.json hovorí aká knižnica a ktorá jej verzia sa má nainštalovať, takže náš package.json upravíme do takejto podoby:

{
  "name": "accounts-dapp",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^15.6.1",
    "react-dom": "^15.6.1",
    "react-scripts": "1.0.13",
    "web3": "1.0.0-beta.18",
    "lodash": "^4.17.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}

Bežiaci npm server zastavíme a spustíme inštaláciu nových dependecies pomocou:

npm install

Keď nám všetko zbehlo korektne, znova spustíme server “npm start”, naskočila nám naša react appka a môžeme s ňou ďalej pracovať.

V tejto časti sa vrátime spať k nášmu SC. Ako sme to robili v predošlej časti, SC skompilujeme, vojdeme do truffle konzoly a zadáme tento kus kódu:

Accounts.deployed().then((e)=>{return JSON.stringify(e.abi)})

Pozornejší si všimli že callback funkcia je zapísaná trocha inak ako minule. Zápis funkcie ()=>{} je formát ES6 a samozrejme je krajší.

To čo nám vrátila konzola sa volá ABI – application binary interface. V skratke to predstavuje štruktúru alebo návod ako má byť SC čítaný z EVM(Ethereum Virtual Machine). Metóda JSON.strigify nám zabezpečila že štruktúra sa nám vypíše ako kus stringu. Ten si skopírujeme do našej appky, resp. momentálne niekde bokom.

Ako ďalší kus kódu zadáme do konzoly:

Accounts.deployed().then((e)=>{return e.address})

Po vykonaní nám vrátilo adresu nášho SC, ktorú si skopírujeme k sebe a použijeme neskôr rovnako ako ABI kód v aplikácii na miestach, ktoré sú vysvetlené v komentároch priamo v kóde.

Teraz sme sa znova dostali do momentu kedy je potrebné vysvetliť kód. Rozhodol som sa že to spravím rovnakým spôsobom ako v predošlom tutoriále, okomentovaním kódu čo najstručnejšie a najvýstižnejšie. Tí developeri, ktorí už majú skúsenosti s Reactom mi môžu určite napísať pripomienky, resp. uvítam nejaké to code review, pretože zatiaľ sa necítim ako “react ninja master”. Tým ostatným odporúčam copypaste a otvoriť dokumentáciu Reactu.

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Web3 from 'web3';
import _ from 'lodash';

var ETHEREUM_CLIENT = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); //spojenie s naším testrpc spusteným lokálne na porte 8545

var accountsContractABI = [{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"account","outputs":[{"name":"firstName","type":"bytes32"},{"name":"lastName","type":"bytes32"},{"name":"age","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_firstName","type":"bytes32"},{"name":"_lastName","type":"bytes32"},{"name":"_age","type":"uint256"}],"name":"addAccount","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"getAccounts","outputs":[{"name":"","type":"bytes32[]"},{"name":"","type":"bytes32[]"},{"name":"","type":"uint256[]"}],"payable":false,"type":"function"}]; //ABI - application binary interface
var accountsContractAddress = '0xad35970639246f196704e799952344aba5684b42'; //adresa nášho smart contractu

var accountsContract = new ETHEREUM_CLIENT.eth.Contract(accountsContractABI, accountsContractAddress);//vytvorí objekt pre solidity contract podľa zadaného ABI a konkrétnej adresy contractu

export default class App extends Component {
  constructor(props) { //metóda pre vytváranie a inicializovanie objektov vytvorených triedou(class)
    super(props)//umožňuje nám prístup k constuctor metóde rodičovskej triedy(parent class)
    this.state = {//objekt, definícia stavov kde si budeme ako pole(array) ukladať dáta
      firstNames: [],
      lastNames: [],
      ages: []
    }
  }

  componentDidMount() {//metóda invokovaná okamžite ako je komponent namountovaný ?alebo rendrovaný? (niesom si istý ako to mám prekladať / súčasť react lifecicle - viď dokumentácia)
    console.log('accountsContract ', accountsContract);
    accountsContract.methods.getAccounts().call().then((result) => {//z vytvoreného objektu ako bolo popísané hore si zavoláme metódu getAccounts() z nášho SC
      this.setState({//callback funkcia nám vráti dáta z SC ktoré setujeme ako state do vytvoreného objektu v konštruktore
        firstNames: String(result[0]).split(','),
        lastNames: String(result[1]).split(','),
        ages: String(result[2]).split(',')
      })
    });
  }

  render() {

    var TableRows = []

    _.each(this.state.firstNames, (value, index) => {
      //spracujeme dáta zo statu do tabuľky pomocou lodash
      //keďže metóda getAccounts() nám vrátila dáta zahashované, pomocou metódy toAscii dáta dekódujeme
      TableRows.push(
        <tr>
          <td>{ETHEREUM_CLIENT.utils.toAscii(this.state.firstNames[index])}</td>
          <td>{ETHEREUM_CLIENT.utils.toAscii(this.state.lastNames[index])}</td>
          <td>{this.state.ages[index]}</td>
        </tr>
      )
    })

    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to Dapp</h2>
        </div>
        <div className="App-Content">
          <div className="container">
            <table>
              <thead>
                <tr>
                  <th>First Name</th>
                  <th>Last Name</th>
                  <th>Age</th>
                </tr>
              </thead>
              <tbody>
              {TableRows}
              </tbody>
            </table>
          </div>
        </div>
      </div>
    );
  }
}

Po uložení kódu v editore sa nám automaticky dappka v prehliadači refreshla. Pokiaľ je všetko v poriadku, zobrazila sa vám prázdna tabuľka so stĺpcami “First name”, “Last name”, “Age”. Zatiaľ nemáme uložené v SC žiadne dáta, preto sa vrátime do truffle konzoly a zadáme:

Accounts.deployed().then((e)=>{return e.addAccount("Ondrej", "Sarnecky", 24)})

Konzola nám vrátila potvrdenie o uložení. V tomto momente ak sa preklikneme do našej dappky a naše dáta sú zobrazené v tabuľke.

Snímka obrazovky 2017-09-10 o 19.14.52

Ak ste sa dostali až sem, gratulujem, práve ste si sami rozbehli svoju prvú dappku. Postupne pracujem na testovaní nových a nových vecí a ako som už skôr spomínal, chystám sa aj na testovanie vlastného ICO-a ku ktorému by som chcel pripraviť komplexnejší tutoriál. Samozrejme všetko bude na blogu. No ak chcete o tom vedieť medzi prvými, odporúčam prihlásiť sa do môjho newslettera. Komplet zdroják som samozrejme commitol na môj Github.

Viac k téme nájdete tu:

Kickstarter na steroidoch + Ethereum Blockchain = ICO

Ak máte záujem nakúpiť Ethereum, odporúčam si prejsť môj návod:

Prvé kroky k Bitcoinu a Ethereu

Related Posts