How to connect an Angular application to a smart contract using web3JS
By: Zoe Koulouris Augustinos
Tags: Smart Contracts, Blockchain Application, Web3, Angular, Dapps

Front-end developers are going to have to interact with smart contracts in the same way that they interact with other web protocols. The web3.js library makes it possible for web developers to connect to an Ethereum node using an HTTP or ICP connection. I am going to show you how to use web3.js in an Angular application.

Taking a step back, it is important to understand that web3 refers to the next generation of the internet made possible by blockchain technology.

Similar to how Web 2.0 can be thought of as a front-end revolution, Web 3.0 can be thought of as a backend revolution. It introduces a collectively managed universal state layer, which allows users to securely transfer value without centralized institutions. Trusted transactions are carried out between anonymous parties through transaction protocols called smart contracts.

My colleagues wrote a smart contract in Solidity on the Ethereum blockchain, called uDonate. uDonate allows people to donate ETH to causes they care about.

In this article, I am going to demonstrate how to interact with a few methods on the uDonate smart contract through an Angular application. I will be interacting with the CreateOrganization, GetOrganization, and DonateETH functions on the smart contract in order to create a new organization and then get an organization that I can donate to.

Getting Set Up

The first step is to install web3.js using npm.

npm install web3

2. You will need a wallet account with test ETH in order to make transactions.

I am using MetaMask. You should install the browser extension and create an account. Once that is set up, you need test ETH to play with for the Ropstein network. You can get ETH from the Ropsetin Ethereum Faucet or from a friend.

3. Create a service in your Angular app and import web3.js into your service file. I created a service called contract.service.ts .

Connecting to Your Wallet

The next step is to add functionality in your application that allows users to connect to their wallet account. I am using a library called Web3Modal because it includes support for multiple providers.

npm install --save web3modal

Follow the instructions in the Github readme. Keep in mind that this library was written in React, so you’ll need to adapt it slightly for Angular and add the necessary components into your service.

I added a button to the homepage that triggers my NgRx user feature. It dispatches an NgRx action called connectUser , which I am listening for in an effect. The effect calls the connectAccount() function in the contract.service.ts file. The connectAccount() function calls web3modal, which allows the user to select their provider. It passes the selected provider to the web3 instance and connects my MetaMask account. If the connectAccount function responds with my user token, the effect dispatches connectUserSuccess and my reducer updates the state.

Now that I am connected, I can interact with a smart contract!

Once the setup is complete, you should be able to connect to your crypto wallet account using web3 and web3modal!

Interacting With the Contract

Add the abis.js file

The first step is to import the smart contract abis.js file into the src folder of your angular app. This file includes all of the functions available on the contract.

The file should export the contract address and the abi in order to import them into the ContractService.

2. Create a new uDonate organization

The uDonate contract’s createOrganization() method takes in four parameters:

function createOrganization(

uint256 id,

address payable wallet,

string memory ens,

address tokenAddress

)

Typically when you do an http POST request, a unique id is generated by the server. Since the contract requires me to pass in a unique id, there’s a use case for a traditional backend. For now, I am hardcoding in the id and passing it along with the parameters that would require user input.

The “address payable wallet” parameter must be a unique wallet address that will accept funds raised for the organization.

The “ens” parameter is a domain name for the wallet address, like “zoe.eth”.

A user can choose whether the organization accepts ETH or DAI. Depending on their selection, a different address will be passed in as the parameter.

I set up a form in a presentational component to take in the required parameters for a new organization. When the user submits the form, the data is passed with an event emitter to the container component. When the data reaches the container component, my createOrganization NgRx action is dispatched, which I am listening for in an effect.

The effect calls the createOrganization() function in the contract.service.ts file.

As you can see in the createOrganization function, the web3 method web3.eth.Contract is being used to create a new contract instance by passing in the uDonate_abi and uDonate_address .

Once you have your contract instance, you can interact with all of the methods and events defined in the json interface object. In this case, we are calling the uDonate createOrganization() method and passing in all of the required parameters.

The .send method is used to send a transaction to the smart contract and execute its method. I passed in the from option to specify the address the transaction should be sent from (my wallet address).

If this works correctly, your MetaMask browser extension should pop up and ask you to confirm the gas fee for the transaction.

If the transaction goes through successfully, my effect will dispatch a createOrganizationSuccess action and my reducer updates the state.

3. Get a uDonate organization

The uDonate contract’s getOrganization() method takes in one parameter:

function getOrganization(uint256 id)

public

view

returns (uint256, address, bool, bool, uint256[] memory)

{

OrganizationObject memory o = organizations[id];

return (o.id, o.wallet, o.paused, o.ended, o.causeIds);

}

I set up a form in a presentational component to take in an ID. Similar to the other features, the data is passed with an event emitter to the container component. The container component dispatches my getOrganization NgRx action, which I am listening to in an effect. The effect calls the getOrganization() function in the contract.service.ts.

The main difference with getOrganization is that we are using the .call method instead of the .send method.

In order to get the account balance of the organization that we are retrieving, I included an additional web3 method getBalence() by passing in the walletAddress that was returned.

If the getOrganization() function responds successfully, the effect will dispatch the getOrganizationSuccess action and the reducer will update the state.

Now we can display a specific organization and its’ account balance.

4. Donate ETH to an organization

The uDonate donateETH() method takes two parameters :

function donateETH(uint256 id, uint256 tipAmount)

When a user gets an organization, the organization ID and wallet balance are displayed in a presentational component. In addition, there is a form to enter a donation amount and a tip amount. When the user submits the form, the organization ID, donation amount, and tip are passed with an event emitter to the container component. The container component dispatches my donate NgRx action, which I am listening to in an effect. The effect calls the donate() function in the contract.service.ts.

When I call the uDonate method donateETH() , I pass in the id and tip. The web3 .send method is used to send a transaction to the smart contract and execute its method. I passed in the from and value options because I am donating from my connected wallet account and the value is the donation amount converted to WEI.

If this works correctly, your MetaMask browser extension should pop up and ask you to confirm the gas fee for the transaction. If the transaction goes through and the donateETH function responds successfully, the effect will dispatch the donateSuccess action and the reducer will update the state.

You should see a history of your contract interactions in Metamask. You can select the contract interaction to view more details or open it up in Etherscan.

And that’s it! We connected to a crypto wallet and interacted with a smart contract on the Ethereum blockchain through an Angular application! I chose to focus on how I interacted with three uDonate functions. There are some interesting things I would like to explore in more depth in the future — like handling smart contract async functions with NgRx, and using a traditional backend along with a smart contract.