BlockstackでDApp入門 Part 2 ~Animal Kingdom編~
HushHubさんで行われたBlockstackのワークショップまとめのPart 2です。Part 1ではBlockstackの概要とアカウント設定およびサンプルアプリの実行を行いました。 Part 2ではチュートリアルに出てくるAnimal KingdomとApp.coへのアプリ追加を行います。We appreciate for Louis Ivan from Amsterdam his enthusiasm and his visit at HashHub for the workshop.
以下の太字のものをPart 2では記載しています。
- Blockstackとは(再掲)
- Blockstack DApp
- Blockstack ID、Netlifyアカウント作成
- 環境構築
- Animal Kingdomのカスタマイズ
- アプリケーションデプロイ(Netlify)
- App.coへのアプリ追加とApp Mining
Blockstackとは
ブロックチェーンの仕組みを利用して非中央集権型のアプリケーションを作成できるプラットフォームです。Blockstackではブロックチェーン技術を認証とデータ保存に使用しています。ユーザの暗号鍵、データは全てユーザの所有とされ、Blockchain Name Service および Blockchain & P2P Network と各種API(下図のIdentity API、Storage API、Tokens API)がBlockstackアプリと連携することで動作するようになっています。[2]
インターネットの上にTCP/IPの層があり、その上にBlockstackのブロックチェーンとBlockstackのソフトウェア層、その上に作成したDAppが展開されるアーキテクチャになっています。ユーザのIDやデータが管理主体から切り離されているため従来の中央集権型サービスのような情報漏洩や企業によるデータの独占といった懸念が緩和されます。
Animal Kingdomのカスタマイズ
カスタマイズの前にAnimal Kingdomのアプリケーション動作とコードを確認しました。 https://animalkingdoms.netlify.com/へアクセスして、Part 1で取得したBlockstack IDでサインインします。[3]
Web App版のBlockstackブラウザでIDを作成しておく必要があります。
サインインするとAnimal Kingdomのラインディングページへと遷移します。
Animal Kingdomの目的は自身の動物王国を作ることです(なんと、そのままですねw)。好きな動物と土地をそれぞれ選択し、最下部の『Done』をクリックすることでGaiaへデータを保持することができるようになります。
動物王国の主として森で犬を支配できました。
またBlockstack Explorerから保存されたデータを閲覧することが可能となっています。[4]
(検索窓に自身のBlockstack IDを入力して検索、ユーザプロファイルの『View Raw Profile Data』をクリックして、jsonデータの”apps”の要素)
githubからコードをcloneしてください。コード内容を確認してからカスタマイズしていきます。[5]
$ git clone https://github.com/blockstack/animal-kingdom.git
$ cd animal-kingdom
$ ls -al
total 536
drwxrwxr-x 8 User User 4096 Apr 10 20:25 .
drwxrwxr-x 4 User User 4096 Apr 10 20:25 ..
drwxrwxr-x 3 User User 4096 Apr 10 20:25 config
drwxrwxr-x 2 User User 4096 Apr 10 20:25 cors
drwxrwxr-x 8 User User 4096 Apr 10 20:25 .git
-rw-rw-r-- 1 User User 316 Apr 10 20:25 .gitignore
-rw-rw-r-- 1 User User 2639 Apr 10 20:25 package.json
-rw-rw-r-- 1 User User 501057 Apr 10 20:25 package-lock.json
drwxrwxr-x 4 User User 4096 Apr 10 20:25 public
-rw-rw-r-- 1 User User 2353 Apr 10 20:25 README.md
drwxrwxr-x 2 User User 4096 Apr 10 20:25 scripts
drwxrwxr-x 2 User User 4096 Apr 10 20:27 src
Animal KingdomではReactが使用されていますが、他のJavascriptのライブラリでコーディングすることもできます。Blockstackはライブラリフリーなので、VueやNext.jsでも問題ないと思います。JSX/ES6あたりの理解はもはや必須のようです(-_-;)。 blockstack.js
ライブラリはアプリ側からBlockstack IDを認証し、Gaiaにあるユーザデータを読み書きするために必要で、Blockstack DAppには必ず必要なライブラリといえます。
ユーザ識別子(ID)の認証
src/App.js
ファイルのnew UserSession()
でユーザセッションを作成し、isUserSignedIn()
にてユーザがサインイン状態かどうか判別しています。サインイン状態であれば src/SignedIn
ページを、サインイン状態でなければsrc/Landing
ページを表示します。
import React, { Component } from 'react'
import './App.css'
import { UserSession } from 'blockstack'
import Landing from './Landing'
import SignedIn from './SignedIn'
class App extends Component {
constructor() {
super()
this.userSession = new UserSession()
}
componentWillMount() {
const session = this.userSession
if(!session.isUserSignedIn() && session.isSignInPending()) {
session.handlePendingSignIn()
.then((userData) => {
if(!userData.username) {
throw new Error('This app requires a username.')
}
window.location = `/kingdom/${userData.username}`
})
}
}
render() {
return (
<main role="main">
{this.userSession.isUserSignedIn() ?
<SignedIn />
:
<Landing />
}
</main>
);
}
}
export default App
次にsrc/Landing.js
を確認します。『Sign in to Blockstack』ボタンをクリックするとredirectToSignIn
がコールされ、サインインの認証画面へとリダイレクトされます。BlockstackブラウザでBlockstack IDを作成していない場合は、以下左のようにPart 1でご紹介したBlockstack IDの新規作成の画面となります。
Blockstack IDでサインインが成功するとBlockstack DAppは、ユーザプロファイルの読み込みと、Gaiaのデータの読み書きができるようになります。データはGaia Storage HUBに一意のURLで暗号化されて保存されます。
またUserSession
はセッションデータをブラウザのローカルストレージへ保持するので、今までの中央集権型のアプリケーションの様にセッション状態を中央のサーバやクラウド上のRedisなどで管理しておく必要はありません。
Gaiaでデータ取得と保存
GaiaはBlockstackのデータストレージです( https://hub.blockstack.org)。[6]
src/SignedIn.js
ファイルのloadMe()
メソッドでユーザプロファイルの確認をしています。UserSession
で使用するME_FILENAMEおよびappConfigはsrc/constants.js
に設定があります。
import React, { Component } from 'react'
import { Switch, Route, Redirect } from 'react-router-dom'
import { UserSession } from 'blockstack'
import EditMe from './EditMe'
import Kingdom from './Kingdom'
import NavBar from './NavBar'
import OptionsList from './OptionsList'
import OtherKingdoms from './OtherKingdoms'
import { appConfig, ME_FILENAME } from './constants'
import './SignedIn.css'
loadMe()
メソッド部分。
componentWillMount() {
this.loadMe()
}loadMe() {
const options = { decrypt: false }
this.userSession.getFile(ME_FILENAME, options)
.then((content) => {
if(content) {
const me = JSON.parse(content)
this.setState({me, redirectToMe: false})
} else {
const me = null
this.setState({me, redirectToMe: true})
}
})
}
ユーザが動物と土地を選択して、『Done』をクリックするとsaveMe(me)
メソッドが呼ばれユーザのデータが保存されます。Gaia Storage HUBをデータストアとして使用している場合には、繰り返しになりますが、Blockstack ExplorerからデータのURLを閲覧することが可能です。
Animal Kingdomコード変更
いよいよコード修正です。Animal KingdomのコンポーネントであるTerritories
、Other Kingdoms
へ要素を追加します。まずはwesteros.jpgをpublic/territories
内へ保存してください。
https://docs.blockstack.org/develop/images/westeros.jpg
$ cd public/territories
$ wget https://docs.blockstack.org/develop/images/westeros.jpg
--2019-04-10 21:50:28-- https://docs.blockstack.org/develop/images/westeros.jpg
Resolving docs.blockstack.org (docs.blockstack.org)... 178.128.123.58, 2400:6180:0:d1::575:a001
Connecting to docs.blockstack.org (docs.blockstack.org)|178.128.123.58|:443... connected.
HTTP request sent, awaiting response... 200 OK
westeros.jpg 100%[==============================================>] 14.40K --.-KB/s in 0.08s2019-04-10 21:50:29 (174 KB/s) - saved [14747/14747]$ cd ../../
$ ls public/territories/
forest.jpg tundra.jpg westeros.jpg
src/constants.js
内でTerritories
、Other Kingdoms
の要素を追記します。
export const TERRITORIES = [
{
id: 'forest',
name: 'Forest',
superpower: 'Trees!'
},
{
id: 'tundra',
name: 'Tundra',
superpower: 'Let it snow!'
},
{
id: 'westeros',
name: 'Westeros',
superpower: 'The Iron Throne!'
}
]
Other Kingdoms
は、王国を作成したhttps://animalkingdoms.netlify.comを追加してください。自身のBlockstack IDをruler:へ指定します。
export const OTHER_KINGDOMS = [
{
app: 'https://animal-kingdom-1.firebaseapp.com',
ruler: 'larry.id'
},
{
app: 'http://localhost:3001',
ruler: 'larz.id'
},
{
app: 'https://decentralised-islands.netlify.com',
ruler: 'yannael_leborgne.id'
},
{
app: 'https://thirsty-jang-0c0a17.netlify.com',
ruler: 'ma1222042.id.blockstack'
},
{
app: 'https://animalkingdoms.netlify.com',
ruler: '<YOUR ID>.id.blockstack'
}
]
コード変更ができましたのでnpm startで実行します。環境がローカルで完結している場合は、アプリケーションの動作確認で行ったように動物王国を完成させることができるはずです。
$ npm start> animal-kingdom@1.0.0-alpha.2 start /home/ether/work/blockstack/animal-kingdom
> node scripts/start.js
ランディングページが出てきます。
リモートサーバで動かしている環境では、『Sign in with Blockstack』をクリックすると以下のような認証エラーの画面が出てきました。
オリジン間リソース共有(cross-origin requests, CORs)のエラーで、今回アクセスしているBlockstack DAppからBlockstackブラウザへ認証する際に、クロスオリジンの事象が発生しているためです。
オリジン間リソース共有を解消するため、コードをビルドしてserveでアプリケーションを起動します。
$ npm run build> animal-kingdom@1.0.0-alpha.2 build /home/ether/work/blockstack/animal-kingdom
> node scripts/build.jsCreating an optimized production build...
...You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
For more info visit https://webpack.js.org/guides/code-splitting/Search for the keywords to learn more about each warning.
To ignore, add // eslint-disable-next-line to the line before.File sizes after gzip:416.36 KB build/static/js/main.8ffff9b4.js
863 B build/static/css/main.30d9d418.cssThe project was built assuming it is hosted at the server root.
You can control this with the homepage field in your package.json.
For example, add this to build it for GitHub Pages:"homepage" : "http://myname.github.io/myapp",The build folder is ready to be deployed.
You may serve it with a static server:serve -s buildFind out more about deployment here:http://bit.ly/CRA-deploy
事前にビルドしてできたフォルダ内に、cors/_headers
およびcors/_redirects
をコピーしてからserve -s buildでアプリケーションを起動してみてください。※ビルドの操作は次にNetlify上へアプリケーションを構築する際にも必要となります。
アプリケーションデプロイ(Netlify)
Part 1においてNetlifyというサービスへアカウント登録を行いました。NetlifyはHerokuのようなホスティングサービスで、Githubと連携しCI(Continuous Integration)も構築できます。[7]
まずはAnimal Kingdomのコードをビルドしてオリジン間リソース共有(cross-origin request, CORs)対策のためにbuildフォルダへ必要なファイルをコピーしておきます。
$ npm run build
...$ cp cors/_headers build
$ cp cors/_redirects build
Netlifyへのアプリケーションデプロイは、ビルドしてできたbuildフォルダをドラッグ&ドロップするだけでできます。以下の赤枠の中にbuildフォルダを入れてください。自動でデプロイされ、URLが発行されます。
https://kind-stonebraker-397032.netlify.comというURLでAnimal Kingdomがデプロイされました。クリックするとランディングページへ行くはずなので、Blockstack IDでサインインしてください。
地形に追加したWesterosが表示されていることを確認してください。以下は動物に猫、地形に『Westeros』を選択して『Done』をクリックした結果です。
動物王国の主としてWesterosで猫を支配できました。
ナビゲーションになる『Other Kingdoms』をクリックしてみましょう。https://animalkingdoms.netlify.com/で作成したURLが追加されていることを確認してください。
App.coへのアプリ追加とApp Mining
App.coはBlockstackによって提供されるDAppのマーケットプレースです。Blockstackによって運営されていますが、Blockstackアプリケーションだけでなく、CryptoKittiesなど他のブロックチェーンアプリも登録されています。[8]
App MiningはBlockstackアプリケーションを対象にしたファンドプログラムで基準を満たしたアプリケーションが登録され、毎月ランキングに応じて$100,000がFounderへビットコインで支払われます。上位チームで毎月$20,000相当のビットコインが報酬として支払われています。[9]
それでは先ほどビルドしてデプロイしたAnimal KingdomをApp.coへ登録してみます。App.coの『Add your app』をクリックして必要な事項を入力していきます。
最後まで入力を終えたら『Submit App』をクリックして完了です。
審査がレビュワーによって完了した後に、入力したメールアドレス宛に返信がきます。
以上、ワークショップの内容は完了です。Javascriptでフロントエンドとblockstack.js
ライブラリさえ使えれば簡単なアプリは作成できるので、開発の敷居は非常に低いように感じました。
まとめ
- Blockstackはブロックチェーンの仕組みを利用して非中央集権型のアプリケーションを作成できるプラットフォームである
- Blockstack DAppでは
blockstack.js
ライブラリおよびフロントエンドに使用するJavascriptライブラリを選択してコーディングする - Blockstack DAppはライブラリフリーで、使用するJavascriptのライブラリは自由に選択できる
- App.coにブロックチェーン基盤を問わずDAppを登録することができる
- App Miningへ登録することでBlockstackアプリのランキングへ参加でき、$100,000が上位チームへ支払われる