Đây là phần 5 nằm trong series Lập trình smart contract

Trong bài viết trước, mình đã hướng dẫn xây dựng hợp đồng thông minh trên nền tảng NodeJS. Điểm thiếu sót của bài viết hôm trước đã là chúng ta chưa xây dựng được giao diện cho ứng dụng nên trong bài hôm nay, mình sẽ hướng dẫn cách xây dựng Front End sử dụng được hợp đồng thông minh mà chúng ta đã triển khai lên mạng lưới của Ethereum.

Front end Framework:

Có rất nhiều nền tảng để xây dựng Front End như: Angular, ReactJS và VueJS. Trong bài viết bài này, mình sẽ chọn ReactJS do tính đơn giản trong cách khai báo component của nó.

Toàn bộ source code mình sẽ đẩy lên github tại nodejs-ethereum-frontend:

Kết quả mà chúng ta mong muốn sẽ như thế này:

Thay vì phải tự cấu hình webpack, chúng ta có thể xử một công cụ hỗ trợ tạo project ReactJS có tên là create-react-app. Để cài đặt, ta sử dụng command sau:

npm install -g create-react-app

Sau khi cài đặt xong, ta tạo project có tên là hello-frontend bằng command sau:

create-react-app hello-frontend

Trong project được tạo sẽ có hai thư mục chính là publicsrc. Toàn bộ các component được tạo sẽ được chứa trong thư mục src.

Sau khi khởi tạo xong, ta di chuyển vào thư mục hello-frontend và khởi chạy ứng dụng bằng command:

npm start

Khi đó, bạn sẽ thấy một ứng dụng được xây dựng sẵn tại địa chỉ http://localhost:3000:

Web3:

Toàn bộ các thành phần giao tiếp với nhau như sơ đồ bên dưới. Trong sơ đồ này, thư viện web3 sẽ chứa thành phần là provider. Provider sẽ đóng đóng vai trò cầu nối giữa ứng dụng và mạng lưới blockchain.

Chúng ta sẽ có 2 phiên Web3, một phiên bản mà Metamask sử dụng, một phiên bản dành cho ứng dụng Front End mà chúng ta dự định xây dựng tới đây.

Đối với phiên bản Web3 mà Metamask sử dụng: Khi cài đặt tiện ích mở rộng vào trình duyệt, Metamark mặc định thêm thư viện Web3 vào trình duyệt. Để kiểm tra, bạn có thể mở trình duyệt lên, vào một trang web bất kì, mở Developer Tools bằng cách ấn F12, chuyển qua tab Console và gõ từ web3 và nhấn phím Enter:

Đối với phiên bản Web3 dành cho ứng dụng Front End, chúng ta phải tự cài đặt lấy bằng command sau (nhớ là phải cài đặt version cụ thể là 1.0.0-beta-26 đấy nhé):

npm install --save web3@1.0.0-beta.26

Viết Code:

Bước 1: Web3

chúng ta cần phải tạo component chứa đối tượng web3. Đối tượng web3 này sẽ khởi tạo từ provider của Metamask.

Tạo file web.js trong thư mục src có nội dung như sau:

import Web3 from 'web3';

const web3 = new Web3(window.web3.currentProvider);

export default web3;

Trong đoạn code trên, window.web3.currentProvider chính là provider từ web3 của Metamask. Biến windows ở đây chính là biến global windows mà chúng ta thường dùng trong Javascript. Do web3 được Metamask tự động thêm vào trình duyệt nên ở đây windows sẽ có thêm thuộc tính web3.

Bước 2: Smart contract

Chúng ta cần tạo file chứa nội dung của hợp đồng thông minh.  Chúng ta tạo file có tên là hello.js trong thư mục src, nội dung sẽ bao gồm deployed address và ABI của hợp đồng thông minh đã được deploy ở bài viết trước. Hai thông tin này đã được chúng ta in ra khi deploy lên Rinkeby:

   Nội dung của file hello.js tương tự như bên dưới, nhớ đổi lại address và abi nhé:

import web3 from './web3';

const address = '0x4E36Af2bc003eCf3CF9D6a8f22503A78Da3ddAfe';

const abi = [{ "constant": false, "inputs": [{ "name": "mes", "type": "string" }], "name": "setMessage", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": true, "inputs": [], "name": "getMessage", "outputs": [{ "name": "", "type": "string" }], "payable": false, "stateMutability": "view", "type": "function" }, { "inputs": [{ "name": "mes", "type": "string" }], "payable": false, "stateMutability": "nonpayable", "type": "constructor" }];

export default new web3.eth.Contract(abi, address);

Chúng ta cần lưu ý rằng component  mà chúng ta export ra bằng cách dùng web3.eth.Contract(abi, address) chỉ là bản sao của contract trên mạng lưới blockchain.

Bước 3: Kết nối mọi thứ lại:

Chọn file App.js trong thư mục src. Tiến hành import hai web3 và hello đã tạo. Nội dung của file App.js như sau:

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

class App extends Component {

  state = {
    message: '',
    inputValue: '',
    status: ''
  }

  async componentDidMount() {
    await this.getMessage();
  }

  getMessage = async () => {
    const message = await hello.methods.getMessage().call();
    this.setState({ message });
  }

  onSubmit = async (event) => {
    event.preventDefault();
    const acounts = await web3.eth.getAccounts();
    this.setState({ status: 'Waiting for set message: ' + this.state.inputValue });
    await hello.methods.setMessage(this.state.inputValue).send(
      {
        from: acounts[0]
      }
    );
    this.setState({ status: 'Done' });
    await this.getMessage();
  }

  render() {
    return (
      <div class="App">
        <h2>Hello Contract</h2>
        <p>The message is: {this.state.message}</p>
        <form onSubmit={this.onSubmit}>
          <input onChange={event => this.setState({
            inputValue: event.target.value
          })} />
          <button>Set</button>
        </form>
        <p>{this.state.status}</p>

      </div>
    );
  }
}

export default App;

Đoạn code có thể gây khó hiểu cho những ai không biết ReactJS. Nhưng quan trọng nhất là chúng ta chỉ cần biết cách thao tác để lấy và thiết lập giá trị cho 1 biến trong smart contract. Dựa vào nội dung smart contract mà chúng ta đã deploy, chúng ta sẽ có cách lấy và thiết lập giá trị như sau: Để lấy giá trị của biến message trên Ethereum, ta sử dụng hàm methods.getMessage().call(); Do hàm getMessage() chỉ trả về giá trị nên được định nghĩa trong contract với từ khóa view, do đó sẽ không tiêu tốn Ether để thực thi. Để thay đổi giá trị biến message trên Ethereum, ta sử dụng hàm methods.setMessage().send(); Trong hàm send, ta truyền vào một tài khoản ví và tài khoản này phải có số dư Ether. Nguyên nhân là do chúng cần Ether để chi trả cho việc thực thi một hàm làm thay đổi giá trị.   Vậy là chúng ta hoàn thành front end có sử dụng smart contract rồi đó:  

Kết:

 Chúng ta thấy rằng, tuy ứng dụng của chúng ta đã có giao diện giao tiếp được với hợp đồng thông minh tuy nhiên nó còn phải yêu cầu người dùng cài đặt trước Metamask. Điều này gây khó khăn cho người dùng trong thực tế. Trong bài viết tiếp theo, chúng ta sẽ làm một ứng dụng có thể hoạt động độc lập với Metamask.        


Nhận thấy các bài viết tiếng Việt chuyên về lập trình blockchain còn ít nên tôi quyết định chuyển hướng sang chuyên viết về chủ đề blockchain dành riêng cho lập trình viên. Hi vọng những bài viết này sẽ giúp ích cho các bạn đang muốn theo đuổi lĩnh vực còn khá mới này.

Nếu bạn thấy bài viết hữu ích, bạn có thể ủng hộ tôi vài tách cà phê thông qua MoMo tại đây

Bạn cũng có thể nhờ tôi tư vấn về giải pháp công nghệ thông tin nói chung và blockchain nói riêng (có tính phí) thông qua đây

Series Navigation<< Cài đặt môi trường phát triển smart contract trên máy tính cá nhânLập trình smart contract để tạo NFT kết hợp với Chainklink và IPFS >>