ブロックチェーンゲームの作り方5 所持金表示

[Previous << 4 - 基本編Part4](https://qiita.com/flowcadence/items/27ef976c2f2493146dd6)
[Next >> 6 - プレイヤー登録](https://qiita.com/flowcadence/items/8443d8965a8f98486fa8)

https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a#%E9%96%8B%E7%99%BA%E6%96%B9%E6%B3%95

:::note
**リソースから情報を取り出す**

前回話した通り、所持金のResourceはアカウントを作成した時から持っています。最低限のお金もアカウント作成者が負担してくれます。

この最低限のお金は[アカウントストレージのデポジット費用](https://qiita.com/flowcadence/items/c4c24a01ec3d6b7429e2#storage)だと思ってください。この最低限の所持金は引き出す事ができませんが、その代わりに用意されたストレージを自由に使うことができます。

この所持金の残高を取得するにはCapabilityを使用します。Capabilityって何？という方は[Day3](https://qiita.com/flowcadence/items/2911220eb06a20beea14#resource-capability-%E3%81%9D%E3%81%97%E3%81%A6-entitlement)を読んでみてください。

[**Capability**](https://qiita.com/flowcadence/items/85e1aaf7e41d1134fa6c)はアカウントストレージにあるリソースのメソッドを誰でも呼べるように公開したものですから、FCLを使っていつでも呼び出すことができます。
:::

#### [Why Flow](https://qiita.com/flowcadence/items/b6acebdde2b9a6a417c3#flow-token)
> FLOW（または$FLOW）トークンは、Flowネットワークのネイティブ通貨です。開発者およびユーザーは、FLOWを使用してネットワーク上で取引(transact)を行うことができます。開発者は、ピアツーピア決済(他人同士の決済)、サービス料金徴収、または消費者向け特典(rewards)のために、FLOWを直接アプリに統合することができます。

ということでやっていきます、P2P(ピアツーピア)決済アプリ開発!

:::note warn
💡もし、エミュレータの起動方法やスマートコントラクトのデプロイについて操作に自信がない場合は[こちら](https://qiita.com/flowcadence/items/8cc25249cda37364cac1)を参照してください。
:::

#### スマートコントラクトでゲームを作る

Day3で作ったHelloWorldスマートコントラクトを修正してゲームを作成していきます。
まず、所持金を表示します。

このゲームでは`FungibleToken`と`FlowToken`をインポートしますので、[ここ](https://qiita.com/flowcadence/items/9195f9872874baab611e)を参考に依存関係をflow.jsonにインストールします。
```ruby
flow dependencies install FlowToken FungibleToken 
```
こうすることで、flow.jsonの"dependencies"には以下が追加されます。
```ruby
		"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`を持つこと、としているためです。ただし、実際には支払うことはありません。](https://qiita.com/flowcadence/items/c4c24a01ec3d6b7429e2#storage)

#### 以下がFlowToken所持金を取得するスクリプトです。

```ruby:get_balance.cdc
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で実行します。
```ruby
flow scripts execute ./get_balance.cdc "0xf8d6e0586b0a20c7"
```

`0xf8d6e0586b0a20c7`の部分は開発で使用しているエミュレータアカウントのアドレスであり、flow.jsonの以下の部分です。
```ruby
	"accounts": {
		"emulator-account": {
			"address": "f8d6e0586b0a20c7",
			"key": {
				"type": "file",
				"location": "emulator-account.pkey"
			}
		}
	},
```
Output:
```ruby
Result: 999999999.99600000
```
FlowTokenは十分あるようです。テストネットみたいに追加できないのであらかじめ豊富に用意されているようです。

このFlow Tokenを使ってゲームをしていきます。そのため、この`FLOW`残高は画面のわかりやすいところに表示する必要があります。

#### Webフレームワークを準備
ウォレットを表示するためにはWebフレームワークが必要なので、私はSvelteをインストールしました。(Svelteが1番簡単です)プロジェクト名は`awesome-cardgame`としました。
```ruby
npx sv create awesome-cardgame
```
`awesome-cardgame`のフォルダに入って`npm run dev`を実行すると、`http://localhost:5173/`に初期画面が表示されます。

次に、必要なライブラリをインストールします。
```ruby
npm install --save @onflow/fcl
```
Day1のプロジェクトから`flow.json`と`emulator-account.pkey`を、`awesome-cardgame`プロジェクトの`src`フォルダにコピーして以下コマンドを実行します:
```ruby
flow emulator -v
```
#### Dev Walletを起動する
エミュレータが起動している状態で、以下コマンドを実行します。
```ruby
flow dev-wallet
```
#### HTMLとロジックを書く
メイン画面のロジックを以下のようにします。
```ruby:+page.svelte
<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所持金を取得するスクリプト](https://qiita.com/flowcadence/items/8ff1ed3535bc368f7c68#%E4%BD%95%E6%95%85%E3%82%B2%E3%83%BC%E3%83%A0%E3%81%AA%E3%81%AE%E3%81%8B)の内容をjsで取得するには、以下のようにfcl.queryを使用します。
```ruby:src/scripts.js
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;
};
```
:::note
fcl設定で[`.load({ flowJSON })`を追加している](https://qiita.com/flowcadence/items/8ff1ed3535bc368f7c68#html%E3%81%A8%E3%83%AD%E3%82%B8%E3%83%83%E3%82%AF%E3%82%92%E6%9B%B8%E3%81%8F)為、`import "FlowToken"`は`import FlowToken from 0x0ae53cb6e3f42a79`に実行時に解決されます。
:::

#### 所持金を取得/表示する
これで所持金表示のロジックはすべて準備できましたので、`http://localhost:5173/`にアクセスします。

ログインボタンを押します。
![スクリーンショット 2025-01-01 10.13.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3912821/a3374979-a2df-a4d7-ce5e-4d7daa57a502.png)

Service Accountを押すと一発でログインできます。アカウントは`emulator-account`と同じです。

Service Accountを押します。以下のように画面一番左に残高を表示することが出来ます。

![スクリーンショット 2025-01-01 10.16.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3912821/f462ad73-b750-cf4b-d998-9e9fd3e095c4.png)

:::note warn
ログイン済みですとウォレットログインのポップアップは出ませんのでご注意ください。
:::

***
:::note
Flowでは[Wallet Discovery](https://qiita.com/flowcadence/items/01a1580cb15a359a59ce#wallet-discovery)システムが採用されています。イーサリアムのようにメタマスクをブラウザに登録する必要がなく、一貫した理念のもと、誰にでも触れやすいブロックチェーンアプリの構築が可能になっています。

他のブロックチェーンで開発をしたことがある人にとっては逆にとっつきにくいかも知れませんが、メタマスクを触ったことがない人にとってはこちらの方が非常に使いごこちがいいはずです(私もメタマスクより先にFlowのWallet Discoveryを経験したくちです)。

エミュレータには表示されませんが、テストネットやメインネットではウォレットはBloctoを選択するといいでしょう。BloctoはFlowローンチ時に作られた、やはり同じ理念のもと、ユーザーフレンドリーさが最優先されたウォレットであり、SDKなどもあります。

Wallet DiscoveryによるBloctoなどのウォレットログインはブラウザにウォレットをインストールする必要がない為、以前の形式のHTMLからでもウォレットを呼び出そうと思えば呼び出せます<sup>[1]</sup>。ですからゲーム機のNintendo SwitchやPlay Stationの中でもウォレットを呼び出せるのです<sup>(確かPS Vitaでブラウザ呼び出せたはず)</sup>。これは他のブロックチェーンにはできない、FlowのWallet DiscoveryシステムとBloctoウォレットが持つ大きな優位性です。
:::
<sup>[1]: fcl-jsのNPMパッケージをES5以前のjsファイルにコンパイルすることで可能です。[コンパイル手順はこちら](https://medium.com/@tickets.on.flow/how-to-call-blockchains-wallet-in-flutter-apps-633416720f23)。</sup>

***

この記事のソースコードは[こちら](https://github.com/temt-ceo/awesome-cardgame)にあります。

***
<b>[Previous << 4 - 基本編Part4](https://qiita.com/flowcadence/items/27ef976c2f2493146dd6)
</b>

[Flow blockchain / Cadence version1.0ドキュメント](https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a#%E9%96%8B%E7%99%BA%E6%96%B9%E6%B3%95)

<b>[Next >> 6 - プレイヤー登録](https://qiita.com/flowcadence/items/8443d8965a8f98486fa8)</b>