概要

loom-jsにはLoomProviderがあり、これはWeb3.jsとの統合を可能にする。こうして、Loom DAppチェーン上のEVMとより簡単に統合でき、またTruffleフレームワークを使用してテストやデプロイメント、Solidityスマートコントラクトを扱えるようになる。

Web3

Web3.jsは、公式ドキュメンテーションで次のように説明されている:

Web3.jsはライブラリ・コレクションである。これはHTTPもしくはIPC接続を使用して、ローカル又はリモートのイーサリアムノードとの対話を可能にする。

Loom DAppチェーンではHTTPIPCの代わりに、WebSocketsを用いて通信する。しかしWeb3.jsがその部分の抽象化を行うので、この通信についての深い知識は必要ではない。

LoomProvider

Providerは、Web3.jsのAPIをイーサリアム・ノードに接続するブリッジである。Web3.jsのコールがLoom DAppチェーンとの互換性を持つようにするには、LoomProviderを使用する必要がある。

Loom DAppチェーン上にデプロイされたスマートコントラクトと対話するための良い選択肢として、Web3.jsLoomProviderの組み合わせがある。なぜならWeb3.js はAPIコールの構成を抽象化し、ABIを手動で変換する必要がないからだ。

Truffleフレームワーク

Truffleは公式サイトでこう説明されている:

Truffleは最もポピュラーなイーサリアム開発フレームワークであり、あなたの開発ライフをもっと簡単にするというミッションを持っている。

そして実際にその通りのものとなっている。なぜならTruffleでは以下を含む多くのことが可能なのだ: compiledeploytestdebug

Truffleを使ったデプロイと実行

ダウンロードとインストール

まずはTruffleをインストールする必要がある:

# 現在サポートされているバージョン
npm install -g truffle

Truffleがインストールされたら、ディレクトリを作成してプロジェクトの初期化を行おう:

# ディレクトリを作成しアクセス
mkdir simple-store
cd simple-store

# Truffleを使ってゼロからプロジェクトを初期化
truffle init

新しいディレクトリ構造は次のようになる:

.
├── contracts
│   └── Migrations.sol
├── migrations
│   └── 1_initial_migration.js
├── test
├── truffle-config.js
└── truffle.js

コントラクトの追加とマイグレーション

contractsディレクトリ上で、コントラクトをSolidityにて作成する必要がある。これから使用する有名なSimpleStore.solを説明しよう。set関数は、パラメーターvalueと状態を変更する。さらにget関数は、読み取り専用でコールしても状態は変更されない。NewValueSetというイベントは、次のサンプルのようにパラメーターvalueを持つこととなる:

pragma solidity ^0.4.22;

contract SimpleStore {
  uint value;

  event NewValueSet(uint _value);

  function set(uint _value) public {
    value = _value;
    emit NewValueSet(value);
  }

  function get() public view returns (uint) {
    return value;
  }
}

では次にマイグレーションを追加しよう。Truffleにはマイグレーションの概念があるので、変更や更新のトラッキングが非常に便利となる。 このファイルはマイグレーションのディレクトリ上に作成する必要がある。さらにJavaScriptファイルとして、2_simple_store.jsというふうに、数字の2から始まるファイル名を持たなくてはならない。さらに、その中身は以下のようにする必要がある:

var SimpleStore = artifacts.require("./SimpleStore.sol");

module.exports = function(deployer) {
  deployer.deploy(SimpleStore);
};

完全なTruffle統合のサンプルは、 https://github.com/loomnetwork/truffle-dappchain-example にて利用可能だ。

Loom Truffle Providerのダウンロードと設定

最後に追加するパーツはLoom Truffle Providerである。このプラグインでは、TruffleとLoom DAppチェーン間の接続が提供される(さらにその下にはLoomProviderがある)。 ではインストールしよう:

npm install loom-truffle-provider --save
#または
yarn add loom-truffle-provider

さらに次のサンプルのように、truffle.jsのファイルを編集して必要な設定を追加しよう:

const { readFileSync } = require('fs')
const LoomTruffleProvider = require('loom-truffle-provider')

const chainId    = 'default'
const writeUrl   = 'http://127.0.0.1:46658/rpc'
const readUrl    = 'http://127.0.0.1:46658/query'
const privateKey = readFileSync('./private_key', 'utf-8')

const loomTruffleProvider = new LoomTruffleProvider(chainId, writeUrl, readUrl, privateKey)

module.exports = {
  networks: {
    loom_dapp_chain: {
      provider: loomTruffleProvider,
      network_id: '*'
    }
  }
}

忘れずに、コマンドloom genkey -a public_key -k private_keyを使用してキーを生成しよう。

Truffleデプロイコマンドの実行

これでデプロイコマンドを実行する準備ができた:

だがその前に、Loom DAppチェーンを起動しなくてはならない

truffle deploy --network loom_dapp_chain

もしすでに完了しているデプロイメントをリセットしたい場合は、メソッドtruffle deploy --reset --network loom_dapp_chainを実行しよう

アカウントをさらに追加

LoomTruffleProviderのアカウントにアクセスするには、getProviderEngine関数を使用する必要がある。これはLoomProviderを返却し、accountsAddrList及びaccountsプロパティへとアクセスできるようにする。

const loomTruffleProvider = new LoomTruffleProvider(chainId, writeUrl, readUrl, privateKey)
const loomProvider = loomTruffleProvider.getProviderEngine()

console.log("Accounts list", loomProvider.accountsAddrList)
console.log("Accounts and Private Keys", loomProvider.accounts)

さらにアカウントを追加するには、関数createExtraAccountsを使用すれば良い。

const loomTruffleProvider = new LoomTruffleProvider(chainId, writeUrl, readUrl, privateKey)
loomTruffleProvider.createExtraAccounts(10)

Web3.js と LoomProviderの設定と実行

ダウンロードとインストール

npmを使って、Web3.jsの最新バージョンをダウンロードできる。

npm install web3 --save
# 又は
yarn add web3

さらにLoomProviderをダウンロードしてインストールしよう(loom-jsにて機能)

npm install loom-js --save
# 又は
yarn add loom-js

プロジェクトへの追加と設定

インストール後、Node.jsプロジェクト(Node.jsバージョン8以上 )にWeb3.jsを追加するのは非常に簡単だ。これはWebpackを用いたプロジェクトの場合と同じくらい簡単なはずだ:

// Node.JS 8 または8以上
const Web3 = require('web3')

// ES2016サポートのWebpack
import Web3 from 'web3'

次のステップではLoomProviderを設定しよう。これはNodeJS & Browser Quick Startのサンプルにかなり似ている。

const privateKey = CryptoUtils.generatePrivateKey()
const publicKey = CryptoUtils.publicKeyFromPrivateKey(privateKey)

// クライアントを作成
const client = new Client(
  'default',
  'ws://127.0.0.1:46658/websocket',
  'ws://127.0.0.1:46658/queryws',
)

// 関数呼び出し元のアドレス
const from = LocalAddress.fromPublicKey(publicKey).toString()

// LoomProviderを使って、web3クライアントをインスタンス化 
const web3 = new Web3(new LoomProvider(client, privateKey))

const ABI = [{"anonymous":false,"inputs":[{"indexed":false,"name":"_value","type":"uint256"}],"name":"NewValueSet","type":"event"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]

const contractAddress = '0x...'

// Instantiate the contract and let it ready to be used
const contract = new web3.eth.Contract(ABI, contractAddress, {from})

Web3コントラクトインスランスの実行

SimpleStore.solの宣言が上述されているとすると、set関数及びget関数をより簡単に呼び出すことができる。

// バリューを47に設定
const tx = await contract.methods.set(47).send()

// バリュー47を取得
const value = await contract.methods.get().call()

またイベントをリッスンするには、例えばイベントNewValueSetの場合だと以下のようになる:

contract.events.NewValueSet({}, (err, event) => {
  if (err) {
    return console.error(err)
  }

  console.log('New value set', event.returnValues._value)
})