UnityでSymbolのアカウント残高を取得する

#はじめに
この記事はUnityでゲームを開発していて、かつSymbolブロックチェーンから、例えばアカウントのXYM残高を取得したい時に使う方法を説明します。なお、少し書き換えれば残高以外にもトランザクションの情報やハーベストの情報など、RESTゲートウェイを使ったものであればなんでも取得できます。

https://docs.symbolplatform.com/ja/api.html

他に何ができるの？って方は一度こちらをご覧ください

https://docs.symbolplatform.com/symbol-openapi/v1.0.1/


Unityでゲーム開発をしていながらブロックチェーンに少しでも興味があるかたはぜひ一度お試しください。現在（2021/07）C#のSDKが開発中なので、もっと深いことがUnityで簡単にできるようになるでしょう。その前に少し遊んでみてください。

やることは大きく分けて２つです。

１．Symbolアカウントの情報をHTTP通信で取得する
２．取得した情報をJSON形式に書き換える

#Symbolアカウントの情報をHTTP通信で取得する
Unityで外部サーバーとHTTP通信を行う方法はいくつかあるようですが、今回はUnityWebRequestを使いたいと思います。

早速コードですが

```c#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
```

`UnityEngine.Networking`を使います。


```c#
    void Start()
    {
        StartCoroutine(Coroutine());
    }

    private IEnumerator Coroutine()
    {
        IEnumerator coroutine = GetData();
        yield return StartCoroutine(coroutine);
        string symbolAccountData = (string)coroutine.Current.ToString();
        Debug.Log(symbolAccountData);
    }
```

コルーチンを使っています。

簡単に言うと、Unityでは１フレームごとに処理をしているのでHTTPを通信だと結果が返ってきません。コルーチンを使えばフレームを跨いで結果を取得できます。
実際の通信はこのあとの`GetData`で行いますが、そこで得た結果を文字列に変換し、ログ出力しています。


```c#
    IEnumerator GetData()
    {
        string url = "http://2.dusan.gq:3000/accounts/TB4AGGHOZBL3EVHCYFANFEFYSQVFMHGKLHO72NI";
        UnityWebRequest webRequest = UnityWebRequest.Get(url);
        yield return webRequest.SendWebRequest();

        if (webRequest.result == UnityWebRequest.Result.ConnectionError)
        {
            Debug.Log(webRequest.error);
        }
        else if (webRequest.responseCode == 200)
        {
            yield return webRequest.downloadHandler.text;
        }
    }
```

ここがメインです。今回はテストネットです。
NODEは`2.dusan.gq`をお借りしています。アカウントの情報を取得しているのでエンドポイントはこんな感じですね。
`UnityWebRequest.Get`で結果を受けてエラーが無ければ返します。

まとめると、


```c#:SymbolTest.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class SymbolTest : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(Coroutine());
    }

    private IEnumerator Coroutine()
    {
        IEnumerator coroutine = GetData();
        yield return StartCoroutine(coroutine);
        string symbolAccountData = (string)coroutine.Current.ToString();
        Debug.Log(symbolAccountData);
    }

    IEnumerator GetData()
    {
        string url = "http://2.dusan.gq:3000/accounts/TB4AGGHOZBL3EVHCYFANFEFYSQVFMHGKLHO72NI";
        UnityWebRequest webRequest = UnityWebRequest.Get(url);
        yield return webRequest.SendWebRequest();

        if (webRequest.result == UnityWebRequest.Result.ConnectionError)
        {
            Debug.Log(webRequest.error);
        }
        else if (webRequest.responseCode == 200)
        {
            yield return webRequest.downloadHandler.text;
        }
    }
}
```

はい。ここまでだけででSymbolは使えています。オブジェクトにスクリプトをアタッチし、実行してみてください。ログにアカウントの情報が表示されているはずです。

![スクリーンショット 2021-07-10 15.54.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80081/4ceb48c7-6f1d-127f-822f-0de798d7da52.png)


ただ、このままではただの文字列なので残高だけ取得はできません。JSONにしていきます。


#２．取得した情報をJSON形式に書き換える
C#でJSONに変換するためには、受け取りたいJSONデータのクラス定義をします。
今回はアカウント情報なので以下コピペでいけますが、もしほかのものを使いたければこちらのツールに結果をブチ込むと、なんとクラス定義されたコードが返ってきます。便利ですね〜

https://json2csharp.com/

```c#:SymbolTest.cs
    [System.Serializable]
    public class SupplementalPublicKeys
    {
    }

    [System.Serializable]
    public class ActivityBucket
    {
    public string startHeight;
    public string totalFeesPaid;
    public int beneficiaryCount;
    public string rawScore;
    }

    [System.Serializable]
    public class Mosaic
    {
    public string id;
    public string amount;
    }

    [System.Serializable]
    public class Account
    {
    public int version;
    public string address;
    public string addressHeight;
    public string publicKey;
    public string publicKeyHeight;
    public int accountType;
    public SupplementalPublicKeys supplementalPublicKeys;
    public List<ActivityBucket> activityBuckets;
    public List<Mosaic> mosaics;
    public string importance;
    public string importanceHeight;
    }

    [System.Serializable]
    public class Root
    {
    public Account account;
    public string id;
    }

    private IEnumerator Coroutine()
    {
        IEnumerator coroutine = GetData();
        yield return StartCoroutine(coroutine);
        string symbolAccountData = (string)coroutine.Current.ToString();
        Root symbolAccountDataJson = JsonUtility.FromJson<Root>(symbolAccountData);
        float amount = float.Parse(symbolAccountDataJson.account.mosaics[0].amount) / 1000000;
        Debug.Log(amount);
    }
```

先ほどの`Coroutine`の上部にクラスを付け加えます。注意点として今回はコピペで良いですが、アカウント以外の情報を取得したい場合は各クラスの前に`[System.Serializable]`を書くことを忘れないでください。あと、`Coroutine`も少し書き換えます。

とはいっても単純で、

```c#
Root symbolAccountDataJson = JsonUtility.FromJson<Root>(symbolAccountData);
float amount = float.Parse(symbolAccountDataJson.account.mosaics[0].amount) / 1000000;
```
定義したRootクラスに先ほどの文字列でしかなかったアカウントデータを使い変数`symbolAccountDataJson`に入れ直し？ます。

あとは、XYMの残高である`amount`はmicroXYM（多分）、かつ文字列で取得されるのでfloatにして1000000で割ってあげます。

実行すると

![スクリーンショット 2021-07-10 16.06.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80081/4d0b2d61-a852-5176-7ed6-cb8aa7b4cac8.png)

残高が無事表示されました！！！目的は達成されましたので、以上でこちらの記事を終わります。

繰り返しますがSymbolのAPIで取得できるものであれば同じ方法で取得できます。例えばインポータンスに左右される攻撃力、、ハーベストがあればでレアアイテムGET！

などなど考えうることは色々ありそうです。自分は、ハクスラ系アクションゲームでパラメータは基本ランダム。かつ、ブロックチェーンに刻むことで、譲渡や交換可能。的なことを考えており、またうまく実装できましたらそのへんも記事にしていきたいと思います。

<strong>※実は技術系記事は初めてで、かつ趣味プログラマーなので文字で表現する方法をあまり知らず、おそらく間違った表現をしているかと思われますので、気軽にコメントでご指摘ください。

それでは Unity×Symbol ライフを引き続きお楽しみください。


※参照させていただいた記事
HTTP通信
https://tech.mof-mof.co.jp/blog/unity-http-request/
コルーチンについて
https://tech.mof-mof.co.jp/blog/unity-http-request/#%E3%82%B3%E3%83%AB%E3%83%BC%E3%83%81%E3%83%B3
JSON変換
http://blog.lab7.biz/archives/25307142.html
https://www.fenet.jp/dotnet/column/language/6158/