Introduction

Introduction

This tutorial is to teach you how to integrate your iOS or Android app to the AION network. By leveraging Pockets Mobile SDKs you can easily build any app with just a few lines of code saving you a lot of time and frustration. In this tutorial, we will show you the code as well as an example of how it’s used. If you’d prefer to watch these tutorials as a series of videos, see our video playlists for iOS or Android below and follow along. Both repositories (Android and iOS) are open source:

Walkthrough Videos

Walkthrough Videos

In the video playlists below, Steve Tingris, founder of Dabble Lab, an education partner for Pocket Network, walks through AION DApp development for Android and iOS with Luis and Pabel, our engineer leads. You can go in order or click the playlist button at the top left to select which video you would like to use.

iOS

Watch our playlist for iOS app development.

Android

Watch tutorials on Android app development.

 

Installation

Installation

Before we get started, you will need to install the library into your project. For iOS we will be using Cocoapods and for Android we will be using Jitpack, if you don’t have neither in your project refer to these guides:

After you’ve added your package manager to your project, you can install the library following the instructions below:

iOS

pod 'PocketAion', '~> 0.0.13'

Android

// In your root build.gradle
allprojects {
    repositories {
        maven { url 'https://www.jitpack.io' }
    }
}

// In your module build.gradle
dependencies {
    implementation 'com.github.pokt-network:pocket-android-aion:0.0.3'
}
Configuration

Configuration

In order to process your requests to the AION blockchain you will need an AION compatible Pocket Node. We have setup one for you to use at https://aion.pokt.network. The only configuration you need to specify is the URL of the Pocket AION node you will be connecting to. We do this by implementing a class with the Configuration interface, like in the example below:

iOS

class PocketAionConfiguration: Configuration {
    public var nodeURL: URL {
        get {
            return URL(string: "https://aion.pokt.network")!
        }
    }
}

Android

public class PocketAionConfiguration implements Configuration {
    @Override
    public URL getNodeUrl() throws MalformedURLException {
        return new URL("https://aion.pokt.network");
    }
}

After setting our Configuration class, we will need to initialize a new instance of the PocketAion class:

iOS

PocketAion.shared.setConfiguration(config: PocketAionConfiguration.init())

Android

try {
    PocketAion pocketAion = new PocketAion(new PocketAionConfiguration(), context);
} catch (InvalidConfigurationException e) {
    e.printStackTrace();
}
Creating a Wallet

Creating a Wallet

If you would like to enable your app to create AION wallets, so it can store and send tokens, as well as interact with smart contracts, you can do that. The only requirement you need to specify for creating a wallet is:

  • Subnetwork idenfitier: The subnetworks are essentially the network you would like to create your wallet on. For Aion, the subnetworks are: 256 (Main Network) and 32 (Mastery Testnet).
  • Data contents: Each blockchain has its own requirements for wallets, and the metadata it contains. For AION, it doesn’t require any data, so we will pass a blank argument.

For creating a wallet all we need to do is call the createWallet function, like in the following example:

iOS

let wallet = try? PocketAion.createWallet(subnetwork: "32", data: nil)

Android

try {
    Wallet wallet = this.pocketAion.createWallet("mastery", null);
} catch (CreateWalletException cwe) {
    throw cwe;
}
Importing Wallet

Importing a Wallet

If you want to allow your users to bring their existing AION wallets, you can import an existing wallet using the import feature. All you will need to do to successfully import your wallet is specify a:

  • Private Key: The raw private key string of the wallet.
  • Subnetwork: 256 (Main Network), 32 (Mastery Testnet).
  • Address: The address of the account you’re importing.
  • Data: For AION we can leave this parameter blank.

To do so, let’s call the importWallet function:

iOS

let wallet = try? PocketAion.importWallet(privateKey: "0x0...", subnetwork: "32", address: "0x0...", data: nil)

Android

try {
    Wallet wallet = this.pocketAion.importWallet("0x0...", "32", "0x0...", null);
} catch (ImportWalletException iwe) {
    throw iwe;
}
Read Data from the Blockchain

Read Data from the Blockchain

To query a transaction or other data from the blockchain, we need to define the RPC method and parameters, as well as specify the AION subnetwork we want to query. To learn more about the different RPC methods and their requirements, you can use the AION Wiki as a reference resource. Only methods in the net_ and eth_ namespaces are implemented in this SDK. In the example below we will show you how to query an account’s balance:

iOS

try? PocketAion.eth.getBalance(address: "0x0...", subnetwork: "32", blockTag: BlockTag.init(block: .LATEST), handler: { (result, error) in
    // result is returned as a BigInt, also can be converted using the .toString() function
    // error is the error, if any, returned by the Pocket Node
})

Android

try {
    pocketAion.eth.getBalance(testAccountAddress, null, MASTERY_SUBNETWORK, new RPCCallback<BigInteger>() {
        @Override
        public void onResult(BigInteger result, Exception exception) {
        // Result contains the account balance
        // Exception, if any, contains the error returned by the Pocket Node
        }
    });
} catch (CreateQueryException e) {
    e.printStackTrace();
}
Sending a Transaction

Sending a Transaction

In order to send a transaction, we need to first create a transaction by defining a couple of parameters, and then sign(serialize) all of that data. Once that is completed, we can then write to the blockchain.

Retrieving the transaction count of the Wallet

One of the parameters we need to send a transaction is what is referred to as the nonce, which is just the count of transactions sent by the wallet. We can easily retrieve this value by calling getTransactionCount like in the example below:

iOS

try? PocketAion.eth.getTransactionCount(address: wallet.address, subnetwork: "32", blockTag: BlockTag.init(block: .LATEST), handler: { (result, error) in
    // Result contains a BigInt with the count of transactions
    // Error, if any, contains the error returned by the Pocket Node
})

Android

try {
    pocketAion.eth.getTransactionCount(wallet.getAddress(), null, "32", new RPCCallback<BigInteger>() {
        @Override
        public void onResult(BigInteger result, Exception exception) {
            // Result contains the transaction count
            // Exception, if any, contains the error returned by the Pocket Node
        }
    });
} catch (CreateQueryException e) {
    e.printStackTrace();
}

Sending the Transaction

To send a transaction, we need to define the parameters:

  • Subnetwork: 256 (Main Network), 32 (Mastery Testnet).
  • Nonce: The wallet transaction count.
  • Wallet: Either by creating a new Wallet or importing one.
  • To: The address we wanna send the funds to.
  • Value: The amount of AION we want to send.
  • Data(optional): The hex encoded data of the transaction, if any.
  • NRG (Energy): The total computational steps we’re willing to execute on this transaction, default for sending any AION amount is 21,000.
  • NRG Price (Energy Price): The amount of AMP’s we’re willing to pay per computational step executed. The current price right now is 10,000,000,000, which means 10 AMPs.  This number might seem very big, but because of the way numbers are handled this is actually a very small number. For more information on this please visit the AION Terminology Wiki page.

After we have all these parameters, we just need to use the sendTransaction function:

iOS

let nonce = BigInt.init(0)
let toAddress = "0x0..."
let data = "";
let value = BigInt.init(10000000000)
let nrgPrice = BigInt.init(10000000000)
let nrg = BigInt.init(21000)

try? PocketAion.eth.sendTransaction(wallet: wallet, nonce: nonce, to: toAddress, data: data, value: value, nrgPrice: nrgPrice, nrg: nrg) { (result, error) in
    // The result contains the transaction hash
    // The error, if any, contains the error returned by the Pocket Node
}

Android

String toAddress = "0x0...";
BigInteger nrg = new BigInteger("21000");
BigInteger nrgPrice = new BigInteger("10000000000");
BigInteger value = new BigInteger("10000000000");
BigInteger nonce = new BigInteger("0");

try {
    pocketAion.eth.sendTransaction("32", wallet, toAddress, nrg, nrgPrice, value, null, nonce, new RPCCallback<String>() {
        @Override
        public void onResult(String result, Exception exception) {
            // Result is the transaction hash
            // Exception, if any, is the error returned by the Pocket Node
        }
    });
} catch (CreateTransactionException cte) {
    cte.printStackTrace();
}
Reading and Writing to a Smart Contract

Reading and Writing to a Smart Contract

A smart contract is the backbone to any application using the blockchain to store or process data. Just like any program, any application can read and write to a smart contract stored in the blockchain. To learn more about smart contracts on AION visit their Smart Contract Development Tutorial.

Initial configuration

Before we begin communicating/querying data from a smart contract. We will need to initialize an instance of the AionContract class. To do that, we will need 4 parameters:

  • A PocketAion instance.
  • The ABI of the Smart Contract: The Application Binary Interface is a JSON schema of the contract structure, allowing our class to know which attributes and functions conform the smart contract we’re interacting with. Every time we compile an AION contract, the ABI will be provided to us.
  • Contract Address: Every smart contract instance has a unique identifier in the form of an address. A smart contract is an enhanced wallet with code stored within it.
  • Subnetwork: 256 (Main Network), 32 (Mastery Testnet).

iOS

let pocketAion = PocketAion.init()
let contractAddress = "0x0..."
guard let contractABI = JSON.init(parseJSON: "[...").array else {
    // There was an error parsing the JSON array
    throw PocketError.configurationError
    return nil
}

let aionContract = try AionContract.init(pocketAion: pocketAion, abiDefinition: contractABI, contractAddress: contractAddress, subnetwork: "32")

Android

PocketAion pocketAion = new PocketAion(new PocketAionConfiguration(), context);
JSONArray abiInterface = new JSONArray("[...");
String contractAddress = "0x0...";

AionContract aionContract = new AionContract(pocketAion, abiInterface, contractAddress, "32");

Write to a Smart Contract:

In order to write to a smart contract, you will need to send a special type of transaction making use of the data param, this process has been simplified using the executeFunction call:

  • Function name: The name of the function we will be calling, you can get this from the contract’s ABI.
  • Function parameters: The parameters of the function, which again, you can get from the contract’s ABI.
  • Wallet: The wallet we’ll be sending the transaction from.
  • Nonce: Since we’re sending a transaction we will need the transaction count, you can review the Sending a Transaction section of this tutorial how to obtain this.
  • NRG (Energy): The total computational steps we’re willing to execute on this transaction, default for sending any AION amount is 21,000.
  • NRG Price (Energy Price): The amount of AMP’s we’re willing to pay per computational step executed. The current price right now is 10,000,000,000, which means 10 AMPs.  This number might seem very big, but because of the way numbers are handled this is actually a very small number. For more information on this please visit the AION Terminology Wiki page.
  • Value: Since smart contracts can also hold and distribute funds, you can send AION from your wallet by specifying this parameter. Only smart contract functions with the payable attribute will receive sent funds.

See below an example on how to call a function defined in your smart contract:

iOS

// Solidity function we're calling: function addToState(uint128 a) public
        
let funcParams = [BigInt.init(1)]
let nrg = BigInt.init(50000)
let nrgPrice = BigInt.init(10000000000)
let nonce = BigInt.init(0)
let value = BigInt.init(0)

try? aionContract.executeFunction(functionName: "addToState", wallet: wallet, functionParams: funcParams, nonce: nonce, nrg: nrg, nrgPrice: nrgPrice, value: value, handler: { (result, error) in
    // The result will contain the transaction hash
    // The error, if any, will contain the error sent from the Pocket Node
})

Android

// Solidity function we're calling: function addToState(uint128 a) public

List<Object> functionParams = new ArrayList<>();
functionParams.add(new BigInteger("1"));
BigInteger nrg = new BigInteger("50000");
BigInteger nrgPrice = new BigInteger("10000000000");
BigInteger nonce = new BigInteger("0");
BigInteger value = new BigInteger("0");
try {
    aionContract.executeFunction("addToState", wallet, functionParams, nonce, nrg, nrgPrice, value, new RPCCallback<String>() {
        @Override
        public void onResult(String result, Exception exception) {
            // The result will contain the transaction hash
            // The exception, if any, will contain the error sent from the Pocket Node
        }
    });
} catch (CreateTransactionException cte) {
    cte.printStackTrace();
} catch (CreateQueryException cqe) {
    cqe.printStackTrace();
} catch (AionContractException ace) {
    ace.printStackTrace();
}

Read a Smart Contract:

You can execute any function with the constant attribute without having having to pay NRG for it (you can however specify it optionally). These functions won’t alter the state of the contract in the blockchain. To read a smart contract you will need to use the executeConstantFunction call with the following parameters:

  • Function name: The name of the function we will be calling, you can get this from the contract’s ABI.
  • Function parameters: The parameters of the function, which again, you can get from the contract’s ABI.
  • From address(optional): Specify the wallet that’s sending this query.
  • NRG (Energy, optional): The total computational steps we’re willing to execute on this transaction, default for sending any AION amount is 21,000.
  • NRG Price (Energy Price, optional): The amount of AMP’s we’re willing to pay per computational step executed. The current price right now is 10,000,000,000, which means 10 AMPs.  This number might seem very big, but because of the way numbers are handled this is actually a very small number. For more information on this please visit the AION Terminology Wiki page.
  • Value (optional): Since smart contracts can also hold and distribute funds, you can send AION from your wallet by specifying this parameter. Only smart contract functions with the payable attribute will receive sent funds.

See below an example on how to call a function defined in your smart contract:

iOS

// Solidity function we're calling: function multiply(uint128 a, uint128 b) public constant returns (uint128)
        
var functionParams = [Any]()
functionParams.append(BigInt.init(2))
functionParams.append(BigInt.init(10))
let fromAddress = "0x0..."
let nrg = BigInt.init(50000)
let nrgPrice = BigInt.init(10000000000)
let value = BigInt.init(0)


try? contract.executeConstantFunction(functionName: "multiply", fromAdress: fromAddress, functionParams: functionParams, nrg: nrg, nrgPrice: nrgPrice, value: value, handler: { (result, error) in
    // Result will be a hex string representing the number 20: 0x14
    // Error, if any, will be the error returned by the Pocket Node
})

Android

// Solidity function we're calling: function multiply(uint128 a, uint128 b) public constant returns (uint128)

try {
    // Prepare parameters
    List<Object> functionParams = new ArrayList<>();
    functionParams.add(new BigInteger("2"));
    functionParams.add(new BigInteger("10"));
    String fromAddress = "0x0...";
    BigInteger nrg = new BigInteger("50000");
    BigInteger nrgPrice = new BigInteger("10000000000");
    BigInteger value = new BigInteger("0");


    // Execute function and assert on response
    contract.executeConstantFunction("multiply", fromAddress, functionParams, nrg, nrgPrice, value, new RPCCallback<Object>() {

        @Override
        public void onResult(Object result, Exception exception) {
            // Result will an Object we can cast to String with the hex string representing the number 20: 0x14
            // Exception, if any, will contain the error sent from the Pocket Node
        }
    });
} catch (CreateQueryException cqe) {
    cqe.printStackTrace();
} catch (AionContractException ace) {
    ace.printStackTrace();
}