Creating ERC20 Sample App

This tutorial shows how to create a sample Ethereum Wallet mobile app step by step.

We recommend reading the first part of this tutorial to learn how to create the Ethereum single smart contract.

1. Ethereum client

To work with the Ethereum network, you will need to have access to the Ethereum client that can be installed locally; alternatively, some services can be used instead (for example, infura.io).

Infura.io is free to use, but you do need to identify your requests sent to RPC provider endpoints. To do it, you will need an Access Token. To obtain it, visit the Infura.io registration page for quick registration for the service.

After submitting your registration, you will be given information on how to access INFURA. It will look something like this:

1383

2. ERC20App

Create a new Blank Ionic project and name it ERC20App.
ERC20App has two screens. On the first screen, a user will be able to create an Ethereum account and validate his balance; on the second screen, a user will be able to transfer coins to another user.

Rename Screen1 to UserScreen.
Add a new Screen and name it TransferScreen.

3. Enable the Ethereum functionality into the AppClient

  • Open API Express Generator
  • Select Appery.io as the domain
  • Select any API Express project
  • Press the AppClient Features button
  • Enable the Ethereum support check box
  • Press the Update button
  • Press the Refresh button

Open the AppClientETHSettings Setting service and specify the host https://ropsten.infura.io/1qQWM142H9OFS7WwdbA6
abi

[
	{
		"anonymous": false,
		"inputs": [
			{
				"indexed": true,
				"name": "_owner",
				"type": "address"
			},
			{
				"indexed": true,
				"name": "_spender",
				"type": "address"
			},
			{
				"indexed": false,
				"name": "_value",
				"type": "uint256"
			}
		],
		"name": "Approval",
		"type": "event"
	},
	{
		"constant": false,
		"inputs": [
			{
				"name": "_spender",
				"type": "address"
			},
			{
				"name": "_value",
				"type": "uint256"
			}
		],
		"name": "approve",
		"outputs": [
			{
				"name": "success",
				"type": "bool"
			}
		],
		"payable": false,
		"stateMutability": "nonpayable",
		"type": "function"
	},
	{
		"constant": false,
		"inputs": [
			{
				"name": "_spender",
				"type": "address"
			},
			{
				"name": "_value",
				"type": "uint256"
			},
			{
				"name": "_extraData",
				"type": "bytes"
			}
		],
		"name": "approveAndCall",
		"outputs": [
			{
				"name": "success",
				"type": "bool"
			}
		],
		"payable": false,
		"stateMutability": "nonpayable",
		"type": "function"
	},
	{
		"constant": false,
		"inputs": [
			{
				"name": "_to",
				"type": "address"
			},
			{
				"name": "_value",
				"type": "uint256"
			}
		],
		"name": "transfer",
		"outputs": [
			{
				"name": "success",
				"type": "bool"
			}
		],
		"payable": false,
		"stateMutability": "nonpayable",
		"type": "function"
	},
	{
		"constant": false,
		"inputs": [
			{
				"name": "_from",
				"type": "address"
			},
			{
				"name": "_to",
				"type": "address"
			},
			{
				"name": "_value",
				"type": "uint256"
			}
		],
		"name": "transferFrom",
		"outputs": [
			{
				"name": "success",
				"type": "bool"
			}
		],
		"payable": false,
		"stateMutability": "nonpayable",
		"type": "function"
	},
	{
		"anonymous": false,
		"inputs": [
			{
				"indexed": true,
				"name": "_from",
				"type": "address"
			},
			{
				"indexed": true,
				"name": "_to",
				"type": "address"
			},
			{
				"indexed": false,
				"name": "_value",
				"type": "uint256"
			}
		],
		"name": "Transfer",
		"type": "event"
	},
	{
		"inputs": [],
		"payable": false,
		"stateMutability": "nonpayable",
		"type": "constructor"
	},
	{
		"payable": false,
		"stateMutability": "nonpayable",
		"type": "fallback"
	},
	{
		"constant": true,
		"inputs": [
			{
				"name": "_owner",
				"type": "address"
			},
			{
				"name": "_spender",
				"type": "address"
			}
		],
		"name": "allowance",
		"outputs": [
			{
				"name": "remaining",
				"type": "uint256"
			}
		],
		"payable": false,
		"stateMutability": "view",
		"type": "function"
	},
	{
		"constant": true,
		"inputs": [
			{
				"name": "_owner",
				"type": "address"
			}
		],
		"name": "balanceOf",
		"outputs": [
			{
				"name": "balance",
				"type": "uint256"
			}
		],
		"payable": false,
		"stateMutability": "view",
		"type": "function"
	},
	{
		"constant": true,
		"inputs": [],
		"name": "decimals",
		"outputs": [
			{
				"name": "",
				"type": "uint8"
			}
		],
		"payable": false,
		"stateMutability": "view",
		"type": "function"
	},
	{
		"constant": true,
		"inputs": [],
		"name": "name",
		"outputs": [
			{
				"name": "",
				"type": "string"
			}
		],
		"payable": false,
		"stateMutability": "view",
		"type": "function"
	},
	{
		"constant": true,
		"inputs": [],
		"name": "symbol",
		"outputs": [
			{
				"name": "",
				"type": "string"
			}
		],
		"payable": false,
		"stateMutability": "view",
		"type": "function"
	},
	{
		"constant": true,
		"inputs": [],
		"name": "totalSupply",
		"outputs": [
			{
				"name": "",
				"type": "uint256"
			}
		],
		"payable": false,
		"stateMutability": "view",
		"type": "function"
	},
	{
		"constant": true,
		"inputs": [],
		"name": "version",
		"outputs": [
			{
				"name": "",
				"type": "string"
			}
		],
		"payable": false,
		"stateMutability": "view",
		"type": "function"
	}
]

contractAddress 0x8979456766329825a1758489b6b6dead2eecacdb.

4. UserScreen

Open the UserScreen screen.

Add a Card component and specify it with ng-hide: isAccount.
Select the Header element and specify it with Text: Create Account.

The Card component will be shown only if the Ethereum account is absent.

Select the body part of the Card component.
Add an Input component and specify it with Placeholder: Private Key Password,
type: password, and ng-model: privateKeyPassword.
Add a Button and specify it with Text: Create Account and ng-click: createAccount().

Add another Card component and specify it with ng-show: isAccount.
Select a Header element and specify it with Text: Account.
Select the body part of the Card component.
Add a Lorem ipsum component and specify it with Text: Account: {{account}}.
Add another Lorem ipsum component and specify it with Text: Balance: {{balance}}.

Add a Button and specify it with Text: Refresh, ng-click: init(), and ng-show: isAccount.
Add one more Button and specify it with Text: Transfer, navigate-to: TransferScreen, and ng-show: isAccount.

Add a scope function init() with the following code:

Apperyio.get("AppClientETHGetAccount")({}).then( 
    function(success) { // success callback
        $scope.account = success.account;
        $scope.isAccount = true;

        // read more about using rest services: https://links.appery.io/ve-snippet-rest
        Apperyio.get("AppClientETHCall")({
            'methodName': 'balanceOf',
            'parameters': [$scope.account]
        }).then( 
            function(success) { // success callback
                /*CLICK TO EDIT MAPPING*/
                $scope.balance = success.balance;
                $scope.$apply();
            },
            function(error) { // callback to handle request error

            });

    },
    function(error) { // callback to handle request error
        console.log("No account");
    });

Add a scope function createAccount() with the following code:

Apperyio.get("AppClientETHCreateAccount")({'password' : $scope.privateKeyPassword}).then(
function(success){ // success callback
    $scope.account = success.account;
    $scope.isAccount = true;
    $scope.balance = 0;
    $scope.$apply();
},
function(error){ // callback to handle request error
    console.error(error);
});

5. TransferScreen

Open the TransferScreen screen.

Add an Input component and specify it with Placeholder: Private Key Password, type: password, and ng-model: privateKeyPassword

Add another Input component and specify it with Placeholder: Recipient address and ng-model: recipientAddress.

Add one more Input component and specify it like this:
Placeholder: Amount of tokens and ng-model: tokenAmount.

Add a Button and specify it with Text: Transfer and ng-click: transfer().

Add another Button and specify it with Text: Back and add an attribute back-button.

Add a scope function transfer() with the following code:

Apperyio.get("AppClientETHTransaction")({
            'methodName': 'transfer',
            'parameters': [$scope.recipientAddress, $scope.tokenAmount],
            'password' : $scope.privateKeyPassword 
        }).then(
function(success){ // success callback
    /*CLICK TO EDIT MAPPING*/
    alert("Transaction was created");
},
function(error){ // callback to handle request error
    console.error(error);
});

6. Testing

Pay attention that the created account doesn't have ethers and tokens so it needs to

  • Send some number of ethers to the created account after it has been created
  • Send some number of tokens to the created account after a smart contract has been created.