実録!Uniqys KitでのDApps開発記 第4回「CryptOsushiのフロントエンド」
前回の記事では、CryptOsushiのバックエンドの実装について紹介しました。今回は、CryptOsushiのフロントエンドの実装について詳細に紹介します。
CryptOsushiのページ
CryptOsushiには、3つのページがあります。
マイSushi
マイSushiページは、自分が持っているおすしの一覧を表示するページです。
画面右上のにぎるボタンを押すことで、新しいおすしが生成されマイSushiページのおすし一覧に追加されます。
売るボタンを押すことで自分のおすしを売り出すことができます。また、おすしの売り出しをキャンセルすることも可能です。
Sushiマーケット
Sushiマーケットでは、販売中のおすしを閲覧することができます。
販売されているおすしは所定のgariを支払うことで購入できます。
全てのSushi
すべてのSushiページでは、流通しているすべてのおすしを見ることができます。
もし販売中なら、このページでも購入することが可能です。
Easy Framework との接続
これまでの紹介した機能が、どのようにできているか説明します。
CryptOsushiは、フロントエンドからEasy FrameworkのGatewayを経由してappにREST APIを呼び出すことで、にぎる・売る・買うなどの機能を提供しています。
Easy FrameworkのGatewayと接続するのにもっとも簡単な方法は、Uniqys Kitに含まれるeasy-clientを使うことです。
easy-clientを使用するために、Nuxt.jsのプラグインとして、plugins/easyclient.jsを実装しました。
easy-clientのEasyClientForBrowserをインスタンス化し、アプリケーションのルートに挿入してアプリケーション内から使用できるようにします。
import { EasyClientForBrowser } from '@uniqys/easy-client'const client = new EasyClientForBrowser(process.env.DAPP_ENDPOINT)export default (_, inject) => { inject('client', client)}
nuxt.config.jsで、以下のようにプラグインを取り込みます。ブラウザでのみの実行するので、 ssr: false
とします。
plugins: [ { src: '~plugins/webfontloader', ssr: false }, { src: '~plugins/easyclient', ssr: false },],
これで、アプリケーション内で以下のように使用できるようになりました。
this.$client.post('/sushi/generate', {}, { sign: true })
app側の実装は、こちらを参照ください。
storeの実装
CryptOsushiのアプリケーションの状態を管理するために、Vuex ストアを利用しています。
sushi
おすしの状態は、state/sushi.jsで実装されています。詳しい実装は、ソースコードをご確認ください。
- fetch
appから画面上に表示されるおすしの一覧を取得し、状態を更新します。 - generate
新しいおすしをにぎり、おすしの一覧に追加します。 - sell
選択されたおすしを入力したgariで売り出します。 - buy
販売中のおすしをgariを支払い購入します。
gari
gariの状態は、state/gari.jsで実装されています。詳しい実装は、ソースコードをご確認ください。
fetchというアクションは、所持しているgariの残高を更新します。
async fetch(context) {
const address = context.rootGetters.getMyAddress()
const { data } = await this.$client.get(`/gari/refer/${address}`)
const { balance } = data;
context.commit('setBalance', { newBalance: balance })
},
本来、以下の実装で残高を取得することが可能です。
const { balance } = await this.$client.api.account(this.$client.address.toString())
しかしCryptOsushiでは、初回起動時に10,000 gariを付与するという仕様です。Easy FrameworkのREST APIでは残高の初期値は 0 gari です。そのため、ユーザーが最初から 10,000 gariを所有しているように振る舞うREST APIを用意して、フロントエンドから呼び出しています。これは gari.py の refar_gari
関数で実装されています。
また、 get()
メソッドでは送信者のアドレスがappに渡らないため、アドレスをURLに付けて通信しています。
sushiの画像を生成する
おすしの画像はお皿、ネタ、薬味の3つから構成されています。これらの画像はそれぞれ10枚ずつ用意しています。この3つの画像をおすしのDNAを元に選択し重ねています。
なお、シャリは1種類しかありません・・・。
おすしの画像は、VSushiListItemImage.vueで実装されています。
おすしは256bitのDNAを保持しています。たとえば16進数表示するとこのようなものです。
db37925934a3d3177db64e11f5e0156ceb8a756fee58ded16e549afa607ddb1d
このDNAから4桁ずつ取り出し、パターン数で剰余演算することで、皿、ネタ、薬味の表示する画像を選択しています。
code() { return { dish: this.dnaCache.readUInt16BE(0) % this.pattern, neta: this.dnaCache.readUInt16BE(4) % this.pattern, spice: this.dnaCache.readUInt16BE(8) % this.pattern, }}
無限スクロールの実装
CryptOsushiの各寿司一覧ではUI/UXを考慮して無限スクロールを実装しています。これはすべてのおすしを1度のリクエストで取得するとデータが大量になる可能性があるためです。
「全てのSushi」のおすしは追加されるだけですが、「マイSushi」と「Sushiマーケット」のおすしは削除される可能性があります。この削除される可能性を考慮すると、おすしの情報を愚直にKey Value Store (KVS) 上に保存する場合に、断片化が生じてパフォーマンスが悪化してしまいます。
そのためCryptOsushiのバックエンドではKVS上に連結リストを実装しています。これに合わせてフロントエンドで無限スクロールを実装すると、ユーザーにデータの一部を効率よく見せることができます。
完成!
これで、おすしをにぎり、そのおすしを売買できるようになりました!
実際におすしをにぎってみると、一瞬でトランザクションが完了します。
ほぼリアルタイムに動作しているため、ブロックチェーン上で動いているアプリケーションであることを意識させません。
トランザクションを発行するための手数料もかからないので、カジュアルにおすしをにぎることができます。
Uniqys Kitの仕組みを学習すれば、Uniqys Kitを利用したアプリケーションは使い慣れた言語で書くことができ、とても気軽に実装できることがわかりました。
おわりに
4日間の連載、いかがでしたでしょうか。
DAppsを開発する上で、Uniqys Kitをどのように使えばいいのかを詳細にお伝えしてきました。
Uniqys Kitは以下の特徴を通して、ユーザーにとっても、開発者にとってもDAppsをより身近に感じてもらうことを目指しています。
- トランザクションの待ち時間が短い
- 手数料が安い
- これまでのWebアプリケーションと同じように実装できる
この連載を通して、Uniqys Kitのことを知っていただき、少しでもこれを使ってDAppsを開発してみようと思っていただけたら幸いです。
進化には多様性が必要である。その多様性を作り出すのはあなた自身だ。