Communicating with smart contracts on the Ethereum blockchain is hard. There is already a bit to read about this on the Interwebs, but here is my approach using the latest stable version of Web3 (0.18.4) along with Angular and TypeScript.

Our goal here is getting the balance of a token contract

Some things you’ll need that I won’t explain are

an angular project (we use version 5.0.0)

(More info: https://angular.io/guide/quickstart)

(More info: https://angular.io/guide/quickstart) web3@0.18.4 or higher as dependency

yarn add web3@0.18.4

a smart contract, i’ll be using a token contract on the Rinkeby test network with address 0xbc84f3bf7dd607a37f9e5848a6333e6c188d926c.

(More info on creating contracts: http://solidity.readthedocs.io/en/develop/contracts.html)

Ok let’s go:

First create a service that will be used to call the contracts

ng generate service contracts

Import web3 and declare window (we’ll use that later) and require

(we’ll use that later) and Use require to get a .json containing the contracts ABI. The ABI of the used token contract can be found here: contract code.

import * as Web3 from 'web3';



declare let require: any;

declare let window: any;



let tokenAbi = require('./tokenContract.json'); @Injectable()

export class ContractsService {

}

We’ll initialize Web3 and check if the user is using a dapp browser and is connected to the Rinkeby network. In this example we’ll do this in the Constructor

Then we can initialize the contract using.

@Injectable()

export class ContractsService {

private _account: string = null;

private _web3: any;



private _tokenContract: any;

private _tokenContractAddress: string = "0xbc84f3bf7dd607a37f9e5848a6333e6c188d926c";



constructor() {

if (typeof window.web3 !== 'undefined') {

// Use Mist/MetaMask's provider

this._web3 = new Web3(window.web3.currentProvider);



if (this._web3.version.network !== '4') {

alert('Please connect to the Rinkeby network');

}

} else {

console.warn(

'Please use a dapp browser like mist or MetaMask plugin for chrome'

);

}



this._tokenContract = this._web3.eth.contract(tokenAbi).at(this._tokenContractAddress);

}

Now the basic stuff is done and we can start calling the contract.

Oh no, if we want to get the balance of the current account, we’ll need to get the account of the user first. Let’s create a function for that. Web3 has a function for that this._web3.eth.getAccount() , this is an async call and expects a callback function as argument. But since we’re using TypeScript, let’s make a Promise of this.

private async getAccount(): Promise<string> {

if (this._account == null) {

this._account = await new Promise((resolve, reject) => {

this._web3.eth.getAccounts((err, accs) => {

if (err != null) {

alert('There was an error fetching your accounts.');

return;

}



if (accs.length === 0) {

alert(

'Couldn\'t get any accounts! Make sure your Ethereum client is configured correctly.'

);

return;

}

resolve(accs[0]);

})

}) as string;



this._web3.eth.defaultAccount = this._account;

}



return Promise.resolve(this._account);

}

We will always use this function if we need the current account, but we don’t want to always do the async call, so first check if we already have the current account. Then we’ll wrap the async call with a new Promise and use the resolve function to let the promise know what the result of the call is. If the account is already known, we create a dummy promise that resolves to that known account address. We still need to use the callback function in here, but from, getAccount can be used like a promise.

Now we really can call the smart contract. Like the getAccount function, also all calls to a contract is asynchronous, like a HTTP call to a REST api, we do a call to the contract on the blockchain and wait for the result.

public async getUserBalance(): Promise<number> {

let account = await this.getAccount();



return new Promise((resolve, reject) => {

let _web3 = this._web3;

this._tokenContract.balanceOf.call(account, function (err, result) {

if(err != null) {

reject(err);

}



resolve(_web3.fromWei(result));

});

}) as Promise<number>;

}

The call we want to do is this._tokenContract.balanceOf.call(account, callbackFuction); . Like before, we want to work with a promise instead of a callback function, so we’ll wrap it into new Promise . In here we also create a local variable of this._web3 because we want to use it in the callback but this will be undefined in here.

Voila, that’s it. Now we can get the user’s balance from the smart contract and display it. Let’s do it in the AppComponent

@Component({

selector: 'app-root',

template: `Balance: <span>{{balance}}</span>`,

styleUrls: ['./app.component.css']

})

export class AppComponent {

public balance: number;



constructor(cs: ContractsService) {

cs.getUserBalance().then(balance => this.balance = balance);

}

}

I’ve added a angular-cli project to github with all this code, it can be installed and run with yarn or npm.

Since you guys won’t have tokens on the provided smart contract on Rinkeby, the balance will be 0.

If you like my approach or you have questions, please leave a comment.

Get to Know FundRequest

Website | White paper | Dev Updates | Sign up

Never Miss An Update By Following FundRequest’s Channels

Blog | Telegram | Github | Reddit | Twitter