Vue framework

dao.tokamak.network는 Vue framework(v2.x)를 이용해서 개발되었습니다. Vue framework는 심플하면서도 안정적이기 때문에 선택하게 되었습니다. 특히나 Vue framework는 개발 속도 측면에서 다른 framework보다 월등하다고 판단하였습니다.

프로젝트 화면 구성은 크게 views, containers 그리고 components 3가지로 구성되어 있습니다. views는 라우팅되는 화면의 전체 구성을 담당하고 있고, containers는 비즈니스 로직과 컴포넌트의 배치를 담당합니다. 그리고 components는 화면의 구성 요소들을 담당합니다.

데이터들은 모두 Vuex의 store에서 관리됩니다. store/index.js를 살펴보면 dao.tokamak.network가 어떻게 동작하는지 쉽게 이해할 수 있습니다. 로그인하기 전에는 launch 함수가 호출되는데 이 함수는 서버에서부터 candidate와 agenda 정보들을 가져오게 됩니다. 지갑에 연결하게 되면(로그인 하면) connectEthereum 함수를 호출합니다. 이 함수는 지갑에 연결되어 있는 provider를 이용해서 contract 데이터를 가져옵니다.

web3.js

web3.js는 이더리움 노드와 상호작용할 수 있는 라이브러리입니다. dao.tokamak.network에서도 web3.js 라이브러리를 이용해서 이더리움 노드와 상호작용합니다. 지갑에 연결하기 전에는 회사 전용 infura 노드를 이용합니다. 이 노드는 오직 컨트랙트 데이터 조회만을 위해 사용됩니다. 트랜잭션을 생성하기 위해서는 반드시 지갑을 연결해야 합니다. 지갑을 연결하면 지갑에 연결된 노드와 상호작용해서 트랜잭션을 생성할 수 있습니다.

트랜잭션 생성은 다음과 같이 이루어집니다.

const gasLimit = await contract.methods.something(param)
  .estimateGas({
    from: this.account,
  });

await contract.methods.something(param)
  .send({
    from: this.account,
    gasLimit: Math.floor(gasLimit * 1.2),
  })
  .on('transactionHash', (hash) => {
			// pending transaction
  })
  .on('confirmation', async (confirmationNumber) => {
    if (this.confirmBlock === confirmationNumber) {
			// update front
    }
  })
  .on('receipt', () => {
			// success
  })
  .on('error', () => {
			// failed
  });
  1. estimateGas 함수를 이용해서 gasLimit을 미리 구합니다. (실제 트랜잭션이 실행되면서 gasLimit보다 많은 가스를 사용하게 되면 out of gas 에러가 발생할 수 있기 때문에 실제로 gasLimit 값은 이에 1.2를 곱한 값을 사용합니다.)

  2. 트랜잭션을 생성하고 노드에 보냅니다. 이 함수에 여러 이벤트를 걸 수 있습니다. dao.tokamak.network에서는 transactionHash 이벤트, confirmation 이벤트 그리고 error 이벤트를 사용합니다. transactionHash 이벤트에서는 pendingTransaction에 대한 처리를 합니다. confirmation 이벤트에서는 트랜잭션이 처리된 이후의 화면 갱신과 같은 작업을 수행합니다. 마지막으로 error 이벤트에서는 실패한 트랜잭션 처리를 담당합니다.

@metamask/jazzicon

메타마스크는 어카운트 별로 다른 아이콘이 부여됩니다. dao.tokamak.network에서도 이런 아이콘을 적용하기 위해서 jazzicon이라는 라이브러리를 사용했습니다.

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/826b1960-9b05-432b-94ad-f62b6ab7fa65/Untitled.png

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/3d5ebc57-8322-4ad4-8fe9-c06004570489/Untitled.png

이 아이콘은 다음과 같이 만들어집니다.

  1. 어카운트 주소에서 0x를 제외한 8자리를 가지고 와서 integer로 만듭니다. (어카운트 주소는 16진수이기 때문에 parseInt의 두번째 인자에 16을 넣게 됩니다.)

    iconNumber = parseInt(account.slice(2, 10), 16);
    
  2. 그리고 jazzicon 라이브러리를 이용해서 icon element를 만들고 다른 elemenet에 append 합니다.

    const icon = jazzicon(25, iconNumber);
    
    element.append(icon);