본문 바로가기
블록체인 기술사업 교육/Node.js

블록체인 기술사업 교육 15일차

by Mecodata 2023. 4. 21.

Solidity, Node.js, MySQL 연동

- npm install mysql으로 mysql 라이브러리 설치

- mysql.createConnection({DB 정보})을 객체화하여(con) MySQL과 연동 연동

- 쿼리문 실행 = con.query(쿼리문, 쿼리문에 필요한 파라미터 목록(생략 가능), 쿼리문 이후 실행할 명령(err, result) => {})

※ con.query의 err의 JSON 데이터로 code, errno, sqlState, sqlMessage, sql의 키값들을 가지고 있음

(실질적인 에러 메시지는 sqlMessage에 담겨있음)

- MySQL 연동할 때 ER_NOT_SUPPORTED_AUTH_MODE 에러 발생 시 해결 방법

ALTER USER '아이디'@'주소' IDENTIFIED WITH mysql_native_password BY '비밀번호';

Solidity

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

contract BusSafe {
    uint256 check_count;

    event AddCheck(
        address checker,
        string car_id,
        string check_res,
        string check_etc,
        uint64 check_time
    );

    struct check_list {
        address checker;
        string car_id;
        string check_res;
        string check_etc;
        uint64 check_time;
    }

    check_list[] public checks;

    function AddCheckList(string memory _car_id, string memory _check_res, string memory _check_etc,uint64 _check_time  ) public {
        address _checker = msg.sender;
        checks.push(check_list(_checker , _car_id,_check_res,_check_etc,_check_time));
        check_count ++;
        emit AddCheck(_checker , _car_id,_check_res,_check_etc,_check_time);
    }
    
    function TotalCount() public view returns(uint256) {
            return check_count;
        }

    function GetCheck(uint _index) public view returns(address ,string memory,string memory,string memory,uint64){
        return (checks[_index].checker, checks[_index].car_id,checks[_index].check_res, checks[_index].check_etc, checks[_index].check_time );
    }

    function GetCheckList() public view returns(check_list[] memory){
        return checks;
    }
}

Node.js

const contractInfo = require("./BusSafe.json");

const abi = contractInfo.abi;
const address = contractInfo.address;

const Web3 = require("web3");
const mysql = require("mysql");

// MySQL 연결 설정
const con = mysql.createConnection({
  host: "localhost",
  user: "root",
  password: "root",
  database: "bussafe",
});

// DB 조회
con.connect(function (err) {
  if (err) throw err;

  con.query("SELECT * FROM checkres", function (err, result, fields) {
    if (err) throw err;
    for (var i = 0; i < result.length; i++) {
      console.log(result[i]);
    }
    con.end();
  });
});

const web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:7545"));
const smartContract = new web3.eth.Contract(abi, address);

// 블록체인에 저장 후 DB에도 저장 (실제로 하이브리드로 저장하는 경우가 많다고 함)
async function addCheck(car_id, check_res, check_etc, check_time) {
  accounts = await web3.eth.getAccounts();
  receipt = await smartContract.methods
    .AddCheckList(car_id, check_res, check_etc, check_time)
    .send({
      from: accounts[1],
      gas: 2000000,
    });
  
  // DB에 저장
  var address = receipt.events.AddCheck.address;
  var blockNumber = receipt.events.AddCheck.blockNumber;
  var returnValue = JSON.stringify(receipt.events.AddCheck.returnValues);
  var sql = `INSERT INTO checkres (address, blockNumber, returnValue) VALUES (?, ?, ?);`;

  con.query(
    sql,
    [address, blockNumber, returnValue],
    function (error, results, fields) {
      if (error) throw error;
      con.end();
    }
  );
}

// 배열 길이 조회
async function getCheckNumber() {
  let checkNumber = await smartContract.methods.TotalCount().call();
  console.log(checkNumber);
}

// 배열에서 특정 인덱스의 데이터 조회
async function getCheckInfo(index) {
  let check = await smartContract.methods.GetCheck(index).call();
  console.log(check);
}

// 배열 조회
async function getCheckList() {
  let checkList = await smartContract.methods.GetCheckList().call();
  console.log(checkList);
}

// 발생했던 이벤트들 조회
async function getEvents() {
  await smartContract.getPastEvents(
    "AddCheck",
    { fromBlock: 0, toBlock: "latest" }, // 처음부터 마지막까지 모두
    function (error, events) {
      console.log(events);
    }
  );
}

// getEvents();

// addCheck("대전 09머 1532", "타이어 펑크 발견", "새 타이어로 교체", 20230108);
// getCheckNumber();
// getCheckInfo(0);
// getCheckList();

댓글