Using the Kin SDK for Unity

Will Gikandi
6 min readAug 2, 2019

The Kin blockchain is a fork of the stellar protocol. As such, operations in your app will boil down to the following:

  1. Creating accounts on the blockchain
  2. Funding accounts on the blockchain
  3. Sending payments

You can clone a sample implementation here , with a detailed Tutorial— or you can follow the steps below to get a basic understanding.

Installation

Create an empty Unity project, and install the Kin Unity Plugin and modify your gradle file as described here.

NOTE: The SDK only runs on an Android/iOS device or emulator. The SDK will not run in the unity editor or unity remote -so you will need to compile and run the code in an emulator or device.

Implementation

Create an empty MonoBehaviour script — name it KinWrapper, and declare the Kin namespace:

using Kin;

You can also enable blockchain listeners by adding the following to your MonoBehaviour :

public class KinWrapper : MonoBehaviour, IPaymentListener, IBalanceListener

Instantiating

Next declare instances of the Kin Client and Kin Account

private KinClient kinClient;
private KinAccount kinAccount;

The client handles the native code depending on the platform you are using. (Android or iOS). The account is the main interface you will be using.

Creating an account

Before using the account, you first have to instantiate it through the client.

kinClient = new KinClient(Kin.Environment.Test, "appId");
if (!kinClient.HasAccount())
{
kinAccount = kinClient.AddAccount();
}else{
kinAccount = kinClient.GetAccount(0);
}

The code above first checks to see if a local account exists on the device. If it doesn’t, it creates an account on the device and returns that as a reference.

NOTE: A ‘created account’ is simply a public key and private key generated on the device. These local keys enable the device to communicate with the blockchain.

You can now get the public key (client’s blockchain address) by calling:

kinAccount.GetPublicAddress();

Onboarding/ Funding an account

Because this key only exists locally, you need to ‘on-board’ it to the blockchain. In other words, a special function needs to be called, to fund and register it online. Before this step is done, the address is considered invalid on the blockchain, and cannot receive or make transactions. This is part of the stellar protocol to avoid spam and unnecessary account creation.

You can check if the account has been on-boarded and funded by calling the following function:

kinAccount.GetStatus(GetStatusCallback)
void GetStatusCallback(KinException ex, AccountStatus status)
{
if (status == AccountStatus.Created)
{
}
else
{
}
}

To on-board and fund an account on the test blockchain, you have 3 options:

Option 1: You can do this manually by pasting the address on Kin’s friend-bot service. This will on-board the account for you automatically.

Option 2: You can call the friend-bot through your code as an http request https://friendbot-testnet.kininfrastructure.com/?addr=address_here

public static IEnumerator FundAccount( string publicAddress, Action<bool> onComplete = null )
{
var url = "http://friendbot-testnet.kininfrastructure.com/?addr=" + publicAddress;
var req = UnityWebRequest.Get( url );
yield return req.SendWebRequest(); if( req.isNetworkError || req.isHttpError )
{
Debug.Log( req.error );
if( onComplete != null )
onComplete( false );
}
else
{
Debug.Log( "response code: " + req.responseCode );
Debug.Log( req.downloadHandler.text );
if( onComplete != null )
onComplete( true );
}
}

Option 3: You can use server side code to fund it yourself (which you must do in a production environment). Basically, your client will need to call your server and request to be on-boarded. Your server can then use Kin’s python SDK or node SDK to perform the on-boarding.

Here is a handy python implementation or Node.js implementation you can use for your server.

Calling the implementation from Unity is as simple as follows:

public IEnumerator FundMe(decimal amount, Action<bool> fundCallback = null)
{
WWWForm form = new WWWForm();
form.AddField("address", kinAccount.GetPublicAddress());
form.AddField("amount", amount.ToString());
reqUrl = "http://address.to.your.server";
var req = UnityWebRequest.Post(reqUrl, form);
yield return req.SendWebRequest();
if (req.isNetworkError || req.isHttpError)
{
Debug.LogError(req.error);
fundCallback(false);
}
else
{
fundCallback(true);
}
}

NOTE: Kin has two blockchains. Production and Test. The test blockchain merely has “play currency” that you can run tests on without incurring costs. The production blockchain has real world value Kin

Calling Other Functions

GetBalance()

account.GetBalance(GetBalanceCallback);
void GetBalanceCallback(KinException ex, decimal balance)
{
if (ex == null)
{
Debug.Log( "Balance: " + balance );
}
else
{
Debug.LogError( "Get Balance Failed. " + ex );
}
}

DeleteAccount()

kinClient.DeleteAccount(0);

NOTE: GetBalance() needs a callback because it’s communicating with the blockchain online. DeleteAccount() doesn’t because it simply deletes the private and public keys on the client. Once deleted, these keys can not be recovered.

Handling transactions

Transactions have the following parameters:

  1. Memo: an optional string with extra information.
  2. Address: the address of the recipient
  3. Amount: amount of Kin you are sending (excluding fees)
  4. Fee: the fee you will pay for your transaction to be processed by the blockchain. The current fee is 100/100000 KIN. This fee protects the blockchain from spam.

NOTE: The fee is denominated in the smallest unit of Kin. (Quark). Just like the smallest unit of a dollar is a cent. So when calling a transaction, set the fee to 100 (quarks) — which is 100/100000 KIN. Setting the fee tells the blockchain you are explicitly agreeing to pay the transaction fee. If you set the fee too low, your transaction will be rejected.

You can view all transactions on Kin’s blockchain at: https://laboratory.kin.org/index.html#explorer?resource=payments

To send a payment, first build the transaction locally :

kinAccount.BuildTransaction(address, amount, fee, memo, BuildTransactionCallBack);

Building a transaction performs several operations on the client to authorise it and sign it. After the transaction is built, use the following callback to send it to Kin’s blockchain.

void BuildTransactionCallBack(KinException ex, Transaction transaction)
{
if (ex == null)
{
kinAccount.SendTransaction(transaction, SendTransactionCallback);
}
else
{
Debug.LogError("Build Transaction Failed. " + ex);
}
}

Once you have sent the transaction to Kin’s blockchain, you can listen for the response, to make sure it went through correctly. A transaction typically takes less than 10 seconds to complete.

void SendTransactionCallback(KinException ex, String transactionId)
{
if (ex == null)
{
//Success
}
else
{
Debug.LogError("Send Transaction Failed. " + ex);
}
}

NOTE: You should use co-routines for functions that need to wait. This will prevent your code from hanging while waiting for responses, and will create a better user experience.

Sending transactions with zero fees

You can send transactions with zero fees by being whitelisted by the Kin Foundation. To get whitelisted, simply register with the Kin Developer Program. Once approved, you can perform an extra step to let your client send transactions with zero fees.

To send a zero-fee transaction after building the transaction:

  1. The client will need to contact your whitelisted server.
  2. Your server will approve/ sign the transaction and send it back to the client.
  3. The client will then send this approved transaction to Kin’s blockchain, and it will be processed for free.

We have already built the transaction, now we whitelist it

void BuildTransactionCallBack(KinException ex, Transaction transaction)
{
if (ex == null)
{
StartCoroutine(WhitelistTransaction(transaction, WhitelistTransactionCallback))
}
else
{
Debug.LogError("Build Transaction Failed. " + ex);
}
}

We are calling our whitelisted server to authorise the transaction

IEnumerator WhitelistTransaction(Transaction transaction, Action<string, string> onComplete)
{
var postDataObj = new WhitelistPostData(transaction);
var postData = JsonUtility.ToJson(postDataObj);
var rawPostData = Encoding.UTF8.GetBytes(postData);
// UnityWebRequest does not work correclty when posting a JSON string so we use a byte[] and a hacky workaround
var req = UnityWebRequest.Post(baseURL + whitelistURL, "POST");
req.SetRequestHeader("Content-Type", "application/json");
req.uploadHandler = new UploadHandlerRaw(rawPostData);
yield return req.SendWebRequest(); if (req.isNetworkError || req.isHttpError)
{
Debug.LogError(req.error);
onComplete(null, null);
}
else
{
onComplete(req.downloadHandler.text, transaction.Id);
}
}

Our server has approved the transaction and sent back a signed string. We now send this signed string to Kin’s blockchain

void WhitelistTransactionCallback(string whitelistTransaction, string transactionId)
{
if (whitelistTransaction != null)
{
kinAccount.SendWhitelistTransaction(transactionId, whitelistTransaction, SendTransactionCallback);
}
else
{
Debug.LogError("Whitelisting Transaction Failed. ");
}
}

As usual, we wait to see if the transaction was successful

void SendTransactionCallback(KinException ex, String transactionId)
{
if (ex == null)
{
//Success
}
else
{
Debug.LogError("Send Transaction Failed. " + ex);
}
}

Before your server has been approved for whitelisting, you can use this pre-approved server in the TEST environment. http://34.239.111.38:3000/whitelist.

public static IEnumerator WhitelistTransaction( Transaction transaction, Action<string> onComplete = null )
{
var postDataObj = new WhitelistPostData( transaction );
var postData = JsonUtility.ToJson( postDataObj );
var rawPostData = Encoding.UTF8.GetBytes( postData );
// UnityWebRequest does not work correclty when posting a JSON string so we use a byte[] and a hacky workaround
var url = "http://34.239.111.38:3000/whitelist";
var req = UnityWebRequest.Post( url, "POST" );
req.SetRequestHeader( "Content-Type", "application/json" );
req.uploadHandler = new UploadHandlerRaw( rawPostData );
yield return req.SendWebRequest(); if( req.isNetworkError || req.isHttpError )
{
Debug.Log( req.error );
if( onComplete != null )
onComplete( null );
}
else
{
Debug.Log( "response code: " + req.responseCode );
Debug.Log( req.downloadHandler.text );
if( onComplete != null )
onComplete( req.downloadHandler.text );
}
}

Once approved, you can use the sample python implementation or Node.js implementation to approve transactions on your server. You can also use the node.js SDK.

Listening to events on the blockchain

You can add listeners to prevent your client from over-querying the blockchain. Simply add the following code

kinAccount.AddPaymentListener(this);
kinAccount.AddBalanceListener(this);
public void OnEvent(PaymentInfo data)
{
//Listening for incoming and outgoing payments
}
public void OnEvent(decimal balance)
{
//Listening for changes in client's balance
}

Putting it all together

You can find this code implemented on: https://github.com/hitwill/kin-sdk-unity-tutorial under the MIT license.

Developer Playbook

You can also check this Developer Playbook — for some higher level concepts of creating with Kin

--

--