Slide 1

Slide 1 text

Dapps 向けの便利な ライブラリを使ってみた Akihiro Tanaka

Slide 2

Slide 2 text

⾃⼰紹介 • 元AccentureのWeb&Mobileエンジニア • 4⽉よりTrident Artsに転職。 • ブロックチェーンを⽤いたサービスを絶賛開発中。

Slide 3

Slide 3 text

使ってみたライブラリ • ethers.js • drizzle • ipfs.js

Slide 4

Slide 4 text

ethers.js This library is designed to make it easier to write client-side JavaScript based wallets, keeping the private key on the owners machine at all times. • Nodeから独⽴してwallet機能をもつ。 • web3の代替となるライブラリ。

Slide 5

Slide 5 text

ethers.js メリット • ウォレットを作成時にノードにアクセスする必要がなく、クライアン ト側で閉じている。 • ライブラリ単体でBIP39&BIP32に対応したウォレットを作成できる。 • Fallback Provider、ENSの設定などサポートしている。 デメリット • web3に依存しているライブラリも存在している、その場合はethers.js では対応できない。 • WebSocketに対応してない。(もうすぐされるかも?)

Slide 6

Slide 6 text

import Web3 from 'web3'; import { default as contract } from 'truffle-contract'; export class Web3Service { private web3: Web3; // 初期化 constructor() { this.web3 = new Web3(new Web3.providers.HttpProvider('https://mainnet.infura.io/')); // this.web3 = new Web3(window.web3.currentProvider); } // コントラクト取得 public async getContract(artifacts: any): Promise { try { const contractAbstraction = contract(artifacts); contractAbstraction.setProvider(this.web3.currentProvider); return await contractAbstraction.deployed(); } catch (error) { throw error; } } // ウォレット作成 getNewWallet(): any { return this.web3.eth.accounts.create(); } }

Slide 7

Slide 7 text

import * as ethers from 'ethers'; export class EthersService { private currentProvider: any; // 初期化 constructor() { const providers = ethers.providers; const network = providers.networks[networkName]; const myProvider = new providers.JsonRpcProvider('http://'); const infuraProvider = new providers.InfuraProvider(network, ''); this.currentProvider = new providers.FallbackProvider([ myProvider, infuraProvider ]); } // コントラクト取得 getContract(abi: any, address: string): any { return new ethers.Contract(address, abi, this.currentProvider); } // ウォレット作成 getNewWallet(): any { return ethers.Wallet.createRandom(); } }

Slide 8

Slide 8 text

ethers.js ethers.jsの概要、実装⽅法 https://qiita.com/biga816/items/2b9d4d4b083e8ec1207f

Slide 9

Slide 9 text

drizzle Drizzle is a collection of front-end libraries that make writing dapp frontends easier and more predictable. The core of Drizzle is based on a Redux store, so you have access to the spectacular development tools around Redux. We take care of synchronizing your contract data, transaction data and more. • コントラクトやトランザクションのデータを⾃動でStoreに同 期してくれる。 • Reduxベースのフロント⽤ライブラリ。(React推し)

Slide 10

Slide 10 text

drizzle メリット • データを参照するに際にコントラクトに直接アクセスする必要がない。 (データが同期されているため、Storeのデータを参照すれば良い。) • コントラクトの呼び出しも可能なため、drizzle単体で完結していてシ ンプル。 デメリット • Web3に依存している。 • WebSocketモードで起動しているノードに接続しないと同期処理が実 ⾏されない。 • Storeのデータが肥⼤化する可能性がある。

Slide 11

Slide 11 text

import SampleContractArtifacts from './../../build/contracts/SampleContract.json'; import { Drizzle, generateStore } from 'drizzle'; export class DrizzleComponent { contracts: any[]; options = { contracts: [ SampleContractArtifacts ], events: { SampleContractArtifacts: ['Hoge'] } }; ngAfterViewInit(): void { // drizzleのstoreを作成する。 const drizzleStore = generateStore(this.options); const drizzle = new Drizzle(this.options, drizzleStore); // window.web3.currentProviderよりwebを取得 drizzle.getWeb3(); drizzle.store.subscribe(() => { this.contracts = drizzle.contracts; }); } }

Slide 12

Slide 12 text

ipfs.js IPFS implementation in JavaScript. • Javascriptでipfsのノードを⽴てることができる。 • ブラウザで動作させることも可能。 • go版はgo-ipfs。

Slide 13

Slide 13 text

ipfs.js メリット • ブラウザで動作させることが可能なため、ipfsノード⽤のサーバーを 別途⽴てる必要がない。 デメリット • パフォーマンスに懸念。 • ノード⽴ち上げ:P2Pネットワーク上でキャッシュの数が⼀定になるように⾃動 でコンテンツを複製し続けているとのことなので、ある程度負荷がある? • データ参照: ⾃前ノードなしだとP2Pネットワーク上にキャッシュを探しに⾏く ことになるが、多少時間がかかる?

Slide 14

Slide 14 text

import { Injectable } from '@angular/core'; import IPFS from 'ipfs'; import * as buffer from 'buffer'; export class IpfsService { ipfs: any; upload(fileBase64: string) { return new Promise((resolve, reject) => { // ノードを⽴ち上げる this.ipfs = new IPFS({ repo: String(Math.random() + Date.now()) }); this.ipfs.on('ready', () => { // ファイルをアップロードする const updFiles = [{ content: buffer.Buffer.from(fileBase64) }]; this.ipfs.files.add(updFiles, (err, files) => { this.ipfs.stop(); if (err) { reject(err); } resolve(files[0].hash); }); }); }); } }

Slide 15

Slide 15 text

Thank you @biga816 akihiro.tanaka.94