Create Publication

We are looking for publications that demonstrate building dApps or smart contracts!
See the full list of Gitcoin bounties that are eligible for rewards.

Solution Thumbnail

Quick and dirty Algorand Unity SDK based on .NET Algorand SDK

Overview

Using AlgorandUnity SDK

Introduction

AlgorandUnity SDK is a comprehensive set of tools that will bring the power of Algorand blockchain within Unity to empower developers to develop Algorand features inside their Unity projects.

With both the C# SDK (.NET platform) and the interface to the Algorand BlockChain (https://github.com/RileyGe/dotnet-algorand-sdk), Unity developers can exploit to integrate the power of Algorand within their work.
The Unity Package will contain:

  • Scripts: Tailored scripts in C# for fast development, to use within a Unity project.
  • Editor: Editor Script to add Unity UI Editor window with Algorand Manager helping Unity developer to configure Algod/PureStake URL Endpoint, Create Wallet/Address, etc.
  • Resources: Public domain resources like materials, textures, meshes, to use with the SDK or for a Unity Developer project.
  • Plugins: All .NET DLL binaries from Algorand C# SDK, useful for cross-platform development, so that a Unity runtime build can be created.
  • Prefabs: Ready-to-use Algorand “prefabs” to be automatically or manually integrated into Unity scenes.
  • Scene Examples: 1 or 2 scenes sample tutorials: How to use Algorand in Unity 3D; basic sample game which uses ALGO tokens, ASA Fungible and Not Fungible Tokens, showing the transfer of Unity Assets via an Algorand transaction in Algorand of ASA NFTs.
  • Documentations: All documentation in MarkDown and PDF format that briefly describes how the SDK works and how to use the included examples.

The whole package will be compatible with the management system used by Unity, as described in the following document: https://docs.unity3d.com/Packages/[email protected]/manual/index.html
and it will also be available through the Assets Store: https://unity3d.com/asset-store/sell-assets

The entire project will be released under the MIT license:
https://opensource.org/licenses/MIT

Open source components and libraries used in the project:

Four main features will be developed:

List of all C# property, methods and events in Algorand SDK: https://rileyge.github.io/dotnet-algorand-sdk/api/index.htm

Algorand Account Management

The centralized AlgorandManager SDK developed for Unity will allow the complete management of the Account of the Algorand BlockChain:

  • Initialization and creation of a new valid offline local Algorand Account
  • Initialization and creation of an online Algorand Account using external KMD endpoint
  • Verification of the formal correctness of an Algorand address
  • Safe saving in the basic game configurations of the created account
  • Retrieval of all essential information: balance, public address, etc …
  • Procedure for deleting an Algorand Account and related deletion of the configuration in Unity.

Payment transaction management in Algorand

Mandatory features to use Algorand within a gaming project include:

  • Configuration of a specific free account for the developer at the address (https://www.purestake.com/technology/algorand-api/) and configuration, through a specific Unity Editor, of parameters such as choice of network to operate on (MAINNET, BETANET, TESTNET), endpoint URL, token-api, etc.
  • Creation, signature and propagation through a free PureStake account of payment transactions in Algo
  • Verification of the transaction and the related block and optional retrieving of its data from the BlockChain
  • Complete management of the main Unity events using template scripts to add on GameObject or using Prefabs.

ASA Trading Transaction Management

As in the Algorand Payment Transactions, the following will be available for ASAs:

  • Create an Asset, FT and NFT
  • Modify an Asset, FT and NFT
  • Receive an Asset, FT and NFT
  • Transfer an Asset, FT and NFT
  • Freeze an Asset, FT and NFT
  • Revoke an Asset, FT and NFT
  • Destroy an Asset, FT and NFT

Retrieve Asset Information

  • Basic search of Transaction, Address and Block using API REST of Explorer.
    It is essential to give the possibility to the single Unity developer to be able to search through the configured Purestake Explorer:
  • Search for all information starting from a Transaction ID
  • Search for all transactions starting from an Algorand Address
  • Search for all information starting from ASA ID
  • Search for all transactions starting from ASA ID

How to install AlgorandUnity SDK

To install SDK you can use different methods:

  • Clonig the repo from Github.
  • Download .unitypackage from https://github.com/Vytek/AlgorandUnitySDK and import using “Import Custom Package”. (See: Link).
  • Download AlgorandUnitySDK-master.zip and extract to your project assets.

How to enable AlgorandUnity SDK Manager Editor

After loading the AlgorandUnitySDK, a new item entitled “Algorand Manager Editor” will be automatically loaded in the main Unity Window Menu. Selecting it will create its floating window.

EditorImages/2021/10/29 14:42/2021-05-28_21-00-57.pngFigure 1-1 Floating Window showing Algorand Manager Editor

It is necessary to set a new token and create a new account of the PureStake service or set URI of your ALGOD/IDX2 Daemons.

EditorImages/2021/10/29 14:40/Unity_2021-05-28_21-01-34.pngFigure 1-2 Unity Editor Menu Endpoint, APIKey, etc…

How to use Algorand Manager Editor

  • Reset: Reset the actual configuration with default parameters.
  • Save Algorand config in PlayerPrefs: After filling in all the necessary fields you can save the configurations in the PlayerPrefs so that they can be used later.
  • Insert Algorand Manager: press to insert AlgorandManager Prefab in your open Scene Hierarchy.
  • Open Developer PureStake: press to open https://developer.purestake.io/ and SignUp for Free/Pay Account to use with AlgorandUnitySDK.

How to use Algorand Manager in your Unity Scripts

After installing the Prefab AlgorandManager in the scene you can use it for development. Installation is possible in two ways:

  • By manually adding the Prefab AlgorandManager (check Prefabs directory);
  • using the “Insert Algorand Manager” option of the Algorand Manager Editor.

Algorand Unity Scripts Example

To see the list of properties, methods and events associated with AlgorandManager, refer to the Documentation folder.
If you want to create a C# script in Unity please see this guide:
https://docs.unity3d.com/Manual/CreatingAndUsingScripts.html

EditorImages/2021/10/29 14:42/Code_2021-05-29_17-45-02.pngFigure 1-3 Syntax highlight code in AlgorandeManager methods and properties

Below is a list with code examples of the methods and properties that the AlgorandManager instance makes available to the Unity developer:

//Show AlgorandManager SDK Version
Debug.Log("AlgorandManager SDK Version: "+AlgorandManager.Instance.Version());
//Create new account
NewAccount = AlgorandManager.Instance.GenerateAccount();
//Show Mnemonic Algorand Account Passphrase
Debug.Log(NewAccount);

WARNING: The GenerateAccount() method returns a Pass Phrase in BIP 39 string format. Keep it secret!

//Reload Algorand Account using Passphrase in AlgorandManager Instance
NewAddress = AlgorandManager.Instance.LoadAccountFromPassphrase(NewAccount);
//Show Algorand Account Address
Debug.Log(NewAddress);
//Get Mnemonic Algorand Account BIP 39 Passphrase 
Debug.Log(AlgorandManager.Instance.GetMnemonicPassphrase());

WARNING: The GetMnemonicPassphrase() method returns a Pass Phrase in BIP 39 string format. Keep it secret!

//Get Algorand Account Address from AlgorandManager Instances
Debug.Log(AlgorandManager.Instance.GetAddressAccount());
//Verify Algorand Account Address passed
Debug.Log("Valid Algorand Address: " + AlgorandManager.Instance.AddressIsValid(NewAddress));

There is an overload of this method with the possibility of further encryption through a password to be asked to the user at runtime. The result of the encryption is not compatible with methods that do not have this additional parameter.

//Save Algorand Account using Passphrase in AlgorandManager Instance in encrypted PlayerPrefs
Debug.Log("Save Algorand Account in encrypted PlayerPrefs: " + AlgorandManager.Instance.SaveAccountInPlayerPrefs(NewAccount));

There is an overload of this method with the possibility of further encryption through a password to be asked to the user at runtime. The result of the encryption is not compatible with methods that do not have this additional parameter.

//Load Algorand Account from encrypted PlayerPrefs
NewAddress = AlgorandManager.Instance.LoadAccountFromPlayPrefs();

If you want to change the saved encrypted account you have to delete it explicitly using method DeleteAccountFromPlayerPrefs() and generating a new Algorand account and then save it.

//Show  ALGOD/PureStake URL saved in PlayerPrefs
Debug.Log("URL ENDPOINT: "+AlgorandManager.Instance.ALGOD_URL_ENDPOINT);

There are also:

  • ALGOD_TOKEN
  • ALGOD_URL_ENDPOINT_INDEXER
//Get Wallet Amount of Algorand Address Account
var amountnow = AlgorandManager.Instance.GetWalletAmount(AlgorandManager.Instance.ALGOD_URL_ENDPOINT, AlgorandManager.Instance.ALGOD_TOKEN, AlgorandManager.Instance.GetAddressAccount());
Debug.Log("MicroAlgos: "+amountnow);
//Get Healthy ( Free 1 req/ 1 sec Purestack for Free Account)
Debug.Log("Algorand Health: "+AlgorandManager.Instance.GetHealth(AlgorandManager.Instance.ALGOD_URL_ENDPOINT_INDEXER, AlgorandManager.Instance.ALGOD_TOKEN));
//Get Account Amount
Debug.Log("Account Amount (KV2XGKMXGYJ6PWYQA5374BYIQBL3ONRMSIARPCFCJEAMAHQEVYPB7PL3KU): "+
AlgorandManager.Instance.GetAccount(AlgorandManager.Instance.ALGOD_URL_ENDPOINT_INDEXER,
AlgorandManager.Instance.ALGOD_TOKEN,
"KV2XGKMXGYJ6PWYQA5374BYIQBL3ONRMSIARPCFCJEAMAHQEVYPB7PL3KU"), false);
//GetAsset Info
var jsonResult = AlgorandManager.Instance.GetAsset(AlgorandManager.Instance.ALGOD_URL_ENDPOINT_INDEXER, 
AlgorandManager.Instance.ALGOD_TOKEN,
15187601);
//Using simple JSON Parser: https://wiki.unity3d.com/index.php/SimpleJSON
var N = JSON.Parse(jsonResult);
//Show Asset Total Example
Debug.Log("Asset Total: "+N["asset"]["params"]["total"]);
//Show Creator Example
Debug.Log("Creator: "+N["asset"]["params"]["creator"]);
//Search last 5 Transactions
var jsonResult = AlgorandManager.Instance.SearchTransactions(AlgorandManager.Instance.ALGOD_URL_ENDPOINT_INDEXER, 
AlgorandManager.Instance.ALGOD_TOKEN, "KV2XGKMXGYJ6PWYQA5374BYIQBL3ONRMSIARPCFCJEAMAHQEVYPB7PL3KU");
//Using simple JSON Parser: https://wiki.unity3d.com/index.php/SimpleJSON
var N = JSON.Parse(jsonResult);
//Debug.Log(jsonResult);
//Show Current Round Example
Debug.Log("Current Round: "+N["current-round"]);
//Transfert Algo from your Accout to another Algorand Address 
Debug.Log("TxID: "+AlgorandManager.Instance.MakePaymentTransaction(AlgorandManager.Instance.ALGOD_URL_ENDPOINT, 
AlgorandManager.Instance.ALGOD_TOKEN,
"KV2XGKMXGYJ6PWYQA5374BYIQBL3ONRMSIARPCFCJEAMAHQEVYPB7PL3KU", 0.01, "Test using AlgorandUnitySDK: "+AlgorandManager.Instance.Version()));

Introduction to simple payment Algorand transaction

There are several scenes in the scenes directory of the project. This document will deal with:

EditorImages/2021/10/29 14:49/Unity_2021-06-02_17-21-34.pngFigure 2-1 List of all Unity Scene/Demo in tutorial Unity package

Click and load “SamplePaySceneAlgorand”.

Code analysis

Tha main code example is the script: StartGameTest.cs

First it is checked if there is a “AlgorandAccountSDK” key and therefore it has been saved.

if (!PlayerPrefs.HasKey("AlgorandAccountSDK"))

If check is true, it will load and show in Debug.Log the account Address used and its mnemonic key in BIP 39 format.

//Load Algorand Account from encrypted PlayerPrefs
NewAddress = AlgorandManager.Instance.LoadAccountFromPlayerPrefs();
//Show Algorand Account Address
Debug.Log(NewAddress);
//Get Mnemonic Algorand Account Passphrase 
Debug.Log(AlgorandManager.Instance.GetMnemonicPassphrase());
NewAccount = AlgorandManager.Instance.GetMnemonicPassphrase();
//Get Algorand Account Address from AlgorandManager Instances
Debug.Log(AlgorandManager.Instance.GetAddressAccount());
//Verify Algorand Account Address passed
Debug.Log("Valid Algorand Address: " + AlgorandManager.Instance.AddressIsValid(NewAddress));
//Show URL ENDPOINT ALGOD
Debug.Log("URL ENDPOINT: " + AlgorandManager.Instance.ALGOD_URL_ENDPOINT);
//Show URL ENDPOINT INDEXER
Debug.Log("URL ENPOINT INDEXER: " + AlgorandManager.Instance.ALGOD_URL_ENDPOINT_INDEXER);
//Show Token Used
Debug.Log("Token Used: " + AlgorandManager.Instance.ALGOD_TOKEN);

Next we will start the background query via UnityThreadQueue of Algorand addresses so as not to interrupt the execution of Unity’s MainThread by modifying the Text Pro at runtime.

Link to UnityThreadQueue:

    //Get Balances Account
    mTextRed.SetText(AmountRed.ToString());
    Debug.Log("Text: "+ mTextRed.text); 
    //mTextBlue =  GameObjectTracker.AllGameObjects [1].gameObject.GetComponent<TextMeshPro>();
    mTextBlue.SetText(AmountBlue.ToString());
    Debug.Log("Text: "+ mTextBlue.text); 
    UnityThreadQueue.Instance.Enqueue(() =>
    {
        //Update Red Balance
        AmountRed = AlgorandManager.Instance.GetWalletAmount(
            AlgorandManager.Instance.ALGOD_URL_ENDPOINT,
            AlgorandManager.Instance.ALGOD_TOKEN,
            "PVT67ZSBADU5ATXRIYBRIDBWSOIJOJJR73FJPCUFSKPHXI4M7PIRS5SRRI"
        );
        //Update blue Balance
        AmountBlue = AlgorandManager.Instance.GetWalletAmount(
            AlgorandManager.Instance.ALGOD_URL_ENDPOINT,
            AlgorandManager.Instance.ALGOD_TOKEN,
            "F52PF5E2GNMUZN2JYPXS4ANMXUY23F6RVE6VEJH4ZZYHMDUZPYUFKWYX6Q"
        );
        Debug.Log("Amount Blue: "+AmountBlue);
        Debug.Log("Amount Red: "+AmountRed);
    });
void Update()
{
    //if ((AmountRed == 0) || (AmountBlue == 0))
    {
        mTextRed.text = AmountRed.ToString();
        mTextBlue.text = AmountBlue.ToString();
    } 
}

Dragging and dropping the “AlgorandCoin” using mouse button onto the blue or red Money Box /Jar will trigger an Algorand payment transaction and play a related sound. When the transaction is completed and confirmed the amount at the top of the cylinder will be updated.

EditorImages/2021/10/29 14:48/Unity_2021-06-02_19-05-07.pngFigure 2-2 Main Game scene demo tutorial

As you can see from the Inspector, both the red jar and the blue moneybox/jar have a script that is triggered when the GameObject AlgoranCoin collides with one of the two jars.

EditorImages/2021/10/29 14:48/Unity_2021-06-02_19-19-46.png

See:

  • “Is Trigger” property flagged on Jar GameObject.
  • “Tag” property set to “AlgorandCoin”.

EditorImages/2021/10/29 14:49/Unity_2021-06-02_19-22-29.pngFigure 2-3 Tag GameObject Editor Inspector

It is very important to understand that you need a system that starts the calls to the various Algorand services in the background and in completely asynchronous mode so as not to interrupt and create problems in the execution of the MainThread of Unity. For this purpose use BackGroundTasksProcessor.cs script.

EditorImages/2021/10/29 14:50/Unity_2021-06-02_19-20-02.pngFigure 2-4 Editor Inspector GameObject configuration for tutorial

void OnTriggerEnter(Collider col)
{
    if (col.tag == "AlgorandCoin")
    {
        Destroy(col.gameObject);
        //Play Sound
        _audioSource.clip = CoinSound;
        _audioSource.Play();
        Debug.Log("AlgorandCoin Collider!");
        //Doing Transaction
        //Using BackgroundTasksProcessor
        Processor.Process(
            () =>
            {
                //Do here Algorand Transaction
                TxIDPayment = AlgorandManager.Instance.MakePaymentTransaction(
                    AlgorandManager.Instance.ALGOD_URL_ENDPOINT,
                    AlgorandManager.Instance.ALGOD_TOKEN,
                    "F52PF5E2GNMUZN2JYPXS4ANMXUY23F6RVE6VEJH4ZZYHMDUZPYUFKWYX6Q",
                    0.01,
                    "Test Tx for Payment: " + DateTime.Now.ToString()
                );
                Debug.Log("TxID: " + TxIDPayment);
                //Update Balance
                Amount = AlgorandManager.Instance.GetWalletAmount(
                    AlgorandManager.Instance.ALGOD_URL_ENDPOINT,
                    AlgorandManager.Instance.ALGOD_TOKEN,
                    "F52PF5E2GNMUZN2JYPXS4ANMXUY23F6RVE6VEJH4ZZYHMDUZPYUFKWYX6Q"
                );
                return Amount;
            },
            (result) =>
            {
                Debug.Log("Amount Blue: " + result);
                //Update Blue Balance
                tempTXT.GetComponent<StartGameTest>().AmountBlue = Amount;
            }
        );
    }
}

See the complete GameObject MoneyBox (Blue Or Red)/Jar configuration on Unity Inspector:

EditorImages/2021/10/29 14:50/Unity_2021-06-02_19-13-40.pngFigure 2-5 Editor Inspector MoneyBoxBlu GameObject configuration for tutorial

Introduction to using NFT on IPFS in Algorand

In this tutorial we will talk about examples of using Assets in Unity.

Two samples scene:

EditorImages/2021/10/29 15:27/Unity_2021-06-02_21-16-15.pngFigure 3-1 Sample scenes in Unity Tutorial Package

Using an Algorand NFT and load from IPFS in Unity

Sample scene: SampleNFTSceneAlgorand

At this link IPFS URI there is very simple mesh in GLFT2.0 format (https://www.khronos.org/gltf/).

It is a Not Fungible Token in Algorand BlockChain.

It is very important to use the indicated JSON library to generate the necessary information for the NFT conforming to the ARC3 specification as indicated in: https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0003.md

See: https://goalseeker.purestake.io/algorand/testnet/asset/15942738

In this tutorial we use: GLTFUtility to load GLB/GLTF 2.0 mesh and render it in Unity.

//Connect to Node
AlgorandManager.Instance.ConnectToNode(AlgorandManager.Instance.ALGOD_URL_ENDPOINT, AlgorandManager.Instance.ALGOD_TOKEN);
//Get info About NFT Asset
var jsonResult = AlgorandManager.Instance.GetAsset(AlgorandManager.Instance.ALGOD_URL_ENDPOINT_INDEXER,
    AlgorandManager.Instance.ALGOD_TOKEN,
    15942738);
//Debug.Log(jsonResult); //DEBUG
//https://wiki.unity3d.com/index.php/SimpleJSON
var N = JSON.Parse(jsonResult);
//Show Asset Total Example
Debug.Log("Asset Total: " + N["asset"]["params"]["total"]);
//Show Creator Example
Debug.Log("Creator: " + N["asset"]["params"]["creator"]);
//Get Asset Algorand NFT
var UrlToNFT = N["asset"]["params"]["url"]; 

To load using UrlToNFT variable we use Unity Coroutine:

IEnumerator LoadGLTFRoutine(string uri)
{
    UnityWebRequest webRequest = new UnityWebRequest(uri);
    webRequest.downloadHandler = new DownloadHandlerBuffer();
    yield return webRequest.SendWebRequest();

    if (webRequest.isNetworkError || webRequest.isHttpError)
    {
        Debug.Log(webRequest.error);
    }
    else
    {
        // Or retrieve results as binary data
        byte[] results = webRequest.downloadHandler.data;
        AnimationClip[] clips;
        GameObject result = Importer.LoadFromBytes(results, new ImportSettings() { useLegacyClips = true }, out clips);
        result.transform.SetParent(contentContainer.transform, false);
    }
}

You can use normal asset trasfer method if you want sell it to specific Algorand Address.

The final result:

EditorImages/2021/10/29 15:26/Unity_2021-06-02_21-30-51.pngFigure 3-2 Unity Editor NFT Scene Example

Transfert Algorand Assets in Unity

Sample scene: SampleASASceneAlgorand

Code analysis

Tha main code example is the script: StartGameASATest.cs

First it is checked if there is a “AlgorandAccountSDK” key and therefore it has been saved.

if (!PlayerPrefs.HasKey("AlgorandAccountSDK"))

If check is true, it will load and show in Debug.Log the account Address used and its mnemonic key in BIP 39 format.

//Load Algorand Account from encrypted PlayerPrefs
NewAddress = AlgorandManager.Instance.LoadAccountFromPlayerPrefs();
//Show Algorand Account Address
Debug.Log(NewAddress);
//Get Mnemonic Algorand Account Passphrase 
Debug.Log(AlgorandManager.Instance.GetMnemonicPassphrase());
NewAccount = AlgorandManager.Instance.GetMnemonicPassphrase();
//Get Algorand Account Address from AlgorandManager Instances
Debug.Log(AlgorandManager.Instance.GetAddressAccount());
//Verify Algorand Account Address passed
Debug.Log("Valid Algorand Address: " + AlgorandManager.Instance.AddressIsValid(NewAddress));
//Show URL ENDPOINT ALGOD
Debug.Log("URL ENDPOINT: " + AlgorandManager.Instance.ALGOD_URL_ENDPOINT);
//Show URL ENDPOINT INDEXER
Debug.Log("URL ENPOINT INDEXER: " + AlgorandManager.Instance.ALGOD_URL_ENDPOINT_INDEXER);
//Show Token Used
Debug.Log("Token Used: " + AlgorandManager.Instance.ALGOD_TOKEN);

Next we will start the background query via UnityThreadQueue of Algorand addresses so as not to interrupt the execution of Unity’s MainThread by modifying the Text Pro at runtime.

UnityThreadQueue.Instance.Enqueue(() =>
{
    //Green
    var jsonResult = AlgorandManager.Instance.GetAccount(AlgorandManager.Instance.ALGOD_URL_ENDPOINT_INDEXER,
    AlgorandManager.Instance.ALGOD_TOKEN, "PVT67ZSBADU5ATXRIYBRIDBWSOIJOJJR73FJPCUFSKPHXI4M7PIRS5SRRI");
    //Debug.Log(jsonResult);
    var N = JSON.Parse(jsonResult);
    //Show Asset Total Example
    Debug.Log("Total Amount for user Green: "+N["account"]["assets"][6]["amount"]);
    AmountGreen = N["account"]["assets"][6]["amount"];
    //PAUSE for PureStake limitation
    Thread.Sleep(2000);
    //Yellow
    jsonResult = AlgorandManager.Instance.GetAccount(AlgorandManager.Instance.ALGOD_URL_ENDPOINT_INDEXER,
    AlgorandManager.Instance.ALGOD_TOKEN, "F52PF5E2GNMUZN2JYPXS4ANMXUY23F6RVE6VEJH4ZZYHMDUZPYUFKWYX6Q");
    N = JSON.Parse(jsonResult);
    //Show Asset Total Example
    Debug.Log("Total Amount for user Yellow: "+N["account"]["assets"][3]["amount"]);
    AmountYellow = N["account"]["assets"][3]["amount"];
});

We have two cube: one yellow and one green.

If you click with right mouse button on one of cubes a new “assets” red bottle wil be created and 1 ASA Algorand will be trasfert to Yellow Address User or Green Address User.

See ASA on TESTNET: https://goalseeker.purestake.io/algorand/testnet/asset/16038175

This is the configuration on Inspector using PoolObject like: https://github.com/Rfrixy/Generic-Unity-Object-Pooler

EditorImages/2021/10/29 15:25/Unity_2021-06-09_13-35-51.pngFigure 4-1 Unity Editor ASA Scene Example

It is very important to understand that you need a system that starts the calls to the various Algorand services in the background and in completely asynchronous mode so as not to interrupt and create problems in the execution of the MainThread of Unity. For this purpose use BackGroundTasksProcessor.cs script.

void OnMouseDown()
{
    Debug.Log("Transfer 1 ASA to Yellow User");
    GameObject bottle = OP.GetPooledObject(bottleIndex);
    bottle.transform.rotation = SpawnPoint.transform.rotation;
    //float xPos = Random.Range(-5f, 5f);
    //float zPos = Random.Range(-5f, 5f);
    bottle.transform.position = SpawnPoint.transform.position;
    bottle.SetActive(true);
    //Transfert ASA
    Processor.Process(
            () =>
            {
                //Do here Algorand ASA Transaction
                TxIDPayment = AlgorandManager.Instance.AssetTransfer(
                AlgorandManager.Instance.ALGOD_URL_ENDPOINT,
                AlgorandManager.Instance.ALGOD_TOKEN,
                "F52PF5E2GNMUZN2JYPXS4ANMXUY23F6RVE6VEJH4ZZYHMDUZPYUFKWYX6Q",
                1,
                16038175,
                "Test Tx for Asset Transfert: " + System.DateTime.Now.ToString());
                Debug.Log("TxID: " + TxIDPayment);
                //PAUSE for PureStake limitation
                Thread.Sleep(4000);
                //Update Balance
                var jsonResult = AlgorandManager.Instance.GetAccount(AlgorandManager.Instance.ALGOD_URL_ENDPOINT_INDEXER,
                AlgorandManager.Instance.ALGOD_TOKEN, "F52PF5E2GNMUZN2JYPXS4ANMXUY23F6RVE6VEJH4ZZYHMDUZPYUFKWYX6Q");
                var N = JSON.Parse(jsonResult);
                //Show Asset Total Example
                Debug.Log("Total Amount for user Yellow: " + N["account"]["assets"][3]["amount"]);
                Amount = N["account"]["assets"][3]["amount"];
                return Amount;
            },
            (result) =>
            {
                Debug.Log("Total Amount Yellow: " + result);
                //Update Blue Balance
                tempTXT.GetComponent<StartGameASATest>().AmountYellow = Amount;
            }
        );
}

A very short video of final result: