Previous << Day4 - 基礎編Part4
Next >> Day6 - プレイヤー登録
Why Flow
FLOW(または$FLOW)トークンは、Flowネットワークのネイティブ通貨です。開発者およびユーザーは、FLOWを使用してネットワーク上で取引(transact)を行うことができます。開発者は、ピアツーピア決済(他人同士の決済)、サービス料金徴収、または消費者向け特典(rewards)のために、FLOWを直接アプリに統合することができます。
ということでやっていきます、猿でも分かるP2P(ピアツーピア)決済アプリ開発!
💡もし、エミュレータの起動方法やスマートコントラクトのデプロイについて操作に自信がない場合はこちらを参照してください。
スマートコントラクトでゲームを作る
Day3で作ったHelloWorldスマートコントラクトを修正してゲームを作成していきます。
まず、所持金を表示します。
このゲームではFungibleToken
とFlowToken
をインポートしますので、ここを参考に依存関係をflow.jsonにインストールします。
flow dependencies install FlowToken FungibleToken
こうすることで、flow.jsonの"dependencies"には以下が追加されます。
"FlowToken": {
"source": "mainnet://1654653399040a61.FlowToken",
"hash": "cefb25fd19d9fc80ce02896267eb6157a6b0df7b1935caa8641421fe34c0e67a",
"aliases": {
"emulator": "0ae53cb6e3f42a79",
"mainnet": "1654653399040a61",
"testnet": "7e60df042a9c0868"
}
},
"FungibleToken": {
"source": "mainnet://f233dcee88fe0abe.FungibleToken",
"hash": "050328d01c6cde307fbe14960632666848d9b7ea4fef03ca8c0bbfb0f2884068",
"aliases": {
"emulator": "ee82856bf20e2aa6",
"mainnet": "f233dcee88fe0abe",
"testnet": "9a0766d93b6608b7"
}
},
何故ゲームなのか
スマートコントラクトはまだ一般人には馴染みが薄いですが、ゲームであれば一般人にも受け入れやすいからです。
全てのアカウントは、初期状態で最低限のFlowTokenを持っています。これはストレージの費用として最低0.001Flow
を持つこと、としているためです。ただし、実際には支払うことはありません。
以下がFlowToken所持金を取得するスクリプトです。
import "FlowToken"
import "FungibleToken"
access(all) fun main(address: Address): UFix64 {
let vaultRef = getAccount(address).capabilities
.borrow<&FlowToken.Vault>(/public/flowTokenBalance)
?? panic("Something wrong happened.")
return vaultRef.balance
}
このスクリプトをFlow CLIで実行します。
flow scripts execute ./get_balance.cdc "0xf8d6e0586b0a20c7"
0xf8d6e0586b0a20c7
の部分は開発で使用しているエミュレータアカウントのアドレスであり、flow.jsonの以下の部分です。
"accounts": {
"emulator-account": {
"address": "f8d6e0586b0a20c7",
"key": {
"type": "file",
"location": "emulator-account.pkey"
}
}
},
Output:
Result: 999999999.99600000
FlowTokenは十分あるようです。テストネットみたいに追加できないのであらかじめ豊富に用意されているようです。
このFlow Tokenを使ってゲームをしていきます。そのため、このFLOW
残高は画面のわかりやすいとことに表示する必要があります。
Webフレームワークを準備
ウォレットを表示するためにはWebフレームワークが必要なので、私はSvelteをインストールしました。(Svelteが1番簡単です)プロジェクト名はawesome-cardgame
としました。
npx sv create awesome-cardgame
awesome-cardgame
のフォルダに入ってnpm run dev
を実行すると、http://localhost:5173/
に初期画面が表示されます。
次に、必要なライブラリをインストールします。
npm install --save @onflow/fcl
Day1のプロジェクトからflow.json
とemulator-account.pkey
をawesome-cardgame
プロジェクトのsrc
フォルダにコピーして以下コマンドを実行する:
flow emulator -v
Dev Walletを起動する
エミュレータが起動している状態で、以下コマンドを実行します。
flow dev-wallet
HTMLとロジックを書く
メイン画面のロジックを以下のようにします。
<script>
import { config, authenticate, unauthenticate, currentUser } from '@onflow/fcl';
import { getBalance } from '../scripts';
import flowJSON from '../flow.json';
const network = 'emulator';
let walletUser;
let flowBalance;
config({
'flow.network': network,
'accessNode.api': 'http://localhost:8888',
'discovery.wallet': 'http://localhost:8701/fcl/authn',
}).load({ flowJSON });
currentUser.subscribe(async (user) => {
walletUser = user;
if (user.addr) {
flowBalance = await getBalance(user.addr);
}
});
</script>
FLOW残高: {flowBalance}
<button onclick={authenticate}>ログイン</button>
<button onclick={unauthenticate}>ログアウト</button>
ログインとログアウトした時にcurrentUser.subscribe
が呼び出されます。ログイン後はuser.addr
があり、ログアウト後はuser.addr
がありません。user.addr
があればgetBalance
を実行します。
残高をjsで取得する
FlowToken所持金を取得するスクリプトの内容をjsで取得するには、以下のようにfcl.queryを使用します。
import { query } from "@onflow/fcl";
export const getBalance = async function (address) {
const result = await query({
cadence: `
import "FlowToken"
import "FungibleToken"
access(all) fun main(address: Address): UFix64 {
let vaultRef = getAccount(address).capabilities
.borrow<&FlowToken.Vault>(/public/flowTokenBalance)
?? panic("Something wrong happened.")
return vaultRef.balance
}
`,
args: (arg, t) => [arg(address, t.Address)],
});
return result;
};
fcl設定で.load({ flowJSON })
を追加している為、import "FlowToken"
はimport FlowToken from 0x0ae53cb6e3f42a79
に実行時に解決されます。
所持金を取得/表示する
これで所持金表示のロジックはすべて準備できましたので、http://localhost:5173/
にアクセスします。
Service Accountを押すと一発でログインできます。アカウントはemulator-account
と同じです。
Service Accountを押します。以下のように画面一番左に残高を表示することが出来ます。
ログイン済みですとウォレットのログインポップアップは出ませんのでご注意ください。
この記事のソースコードはこちらにあります。