Ethereum DApp with Ethers.js and IPFS using Angular, Angular Material and NgRx. Part I

With love to all animals.

A screenshot from the Russian cartoon: Songs for childrenEthereum DApp with Ethers.

js and IPFS using Angular, Angular Material and NgRx.

Part IAlex YevseyevichBlockedUnblockFollowFollowingApr 21In the previous article we began exploring the technique of building an Ethereum smart contract DApp using Angular NgRx.

In this post series, we will dive into a more complicated and interesting case of a Solidity smart contract named FleaMarket.

The source of the inspiration to build this DApp was taken from the blog published by Jackson Ng.

The entire project is built in the VS Code and the complete source code is located at the GitHub repo.

Creating the FleaMarket ContractThe FleaMarket smart contract is written by applying the Factory and Mapping Iterator patterns to the Safe Remote Purchase smart contract.

On every new item putting for sale the FleaMarket contract will spawn a new “child” contract or “assets” represented by the Safe Remote Purchase smart contract.

Smart Contract FleaMarket.

solIt closely resembles the code from the StartEscrow smart contract discussed here.

A few important things to take away from this are:It eliminates the need for face-to-face contact between buyer and seller.

It eliminates the need for a third-party Escrow Agent service.

No need to pay the listing fee.

It motivates both seller and buyer to care the transaction in a fair way from the start to finish by requiring both parties to deposit ETH worth 2x of the value of the item for sale.

Build the Truffle Smart Contract ProjectCreate a new project directory FleaMarketDapp and open it in VS Code.

Open a terminal window and initialize a new Truffle project:truffle initIn .

/contracts folder, add the smart contract file FleaMarket.

sol.

In .

/migrations folder, create a deployment script file 2_deploy_contracts.

js with the following code:var FleaMarket = artifacts.

require("FleaMarket");module.

exports = function(deployer) {deployer.

deploy(FleaMarket);};In the Truffle project configuration file truffle-config.

js, modify the solidity compile version to match the smart contract pragma directive:compiles: { solc: { version: "0.

5.

5", settings: { optimizer: { enable: true, runs: 200 }, } }}Launch a new terminal window and run npm init command to create a default package.

json file.

Next, install the OpenZeppelin smart contract package.

npm install –save openzeppelin-solidityWe use this package to import the SafeMath library in the FleaMarket.

sol file.

Configure Ropsten Network ProviderThe next step is to edit truffle-config.

js file to provide all the necessary configuration for deploying our smart contract to Ropsten.

First we need to authenticate our application with Infura.

Login to Infura and in the Infura Dashboard create a new project:A new project will be setup with a Project ID, along with the link to the corresponding V3 API endpoint URL.

This endpoint URL will be used to send Ethereum requests from our DApp to the Ropsten Ethereum blockchain.

2.

Next, let’s install HD Wallet Provider:npm install –save truffle-hdwallet-providerIn truffle-config.

js,add Ropsten network definition:where, mnemonic is the 12-word secret key for our MetaMask account and infuraProjectToken is the Project ID that has been granted by Infura above.

Notice, that if we skip the last argument in the HDWalletProvider constructor, by default, the account in charge of the smart contract deployment will be the first one generated by the mnemonic.

If we pass in a specific index, it'll use that address instead (the index is zero-based).

Deploying and Validating the Smart ContractNow everything is ready to compile and deploy our smart contract to Ropsten blockchaintruffle migrate –compile-all –reset –network ropstenIn the command window we should see the output similar to this:We can also verify that the smart contract has been deployed successfully by proceeding to the Etherscan to examine our Ethereum Wallet account which we specified in the the HDWalletProvider constructor.

A quick way to test functionality of the smart contract is by using the Truffle console.

truffle console –network ropstenTo get access to the deployed contract instance run the following commands:> let contr = await FleaMarket.

deployed() > contr.

address //‘0x4d0b57A8226a9A1512C22DCe6D643B881853aA43’Next, let’s create a few instances of the child asset contract:> let itemOne = await contr.

createPurchaseContract(‘ITEM00001’, ‘Sport Bike’, ‘0xfile887’) > let itemTwo = await contr.

createPurchaseContract(‘ITEM00002’, ‘Old Hummer’, ‘0xfile556’) > contr.

getKeyCount() //2Finally, invoke the contract function to retrieve a corresponding asset contract address:> contr.

getElementByKey(‘ITEM00001') //‘0xc671DF84F230aa51B076A8cdAa3619Dd3c022558’Setting up the Angular ProjectLet’s get started by installing the latest major versions of the Angular CLI.

npm install -g @angular/cliTo create a new Angular project, open a new terminal in the root folder of our Truffle project and run the following CLI command:ng new ClientApp –skip-install=true –minimal=true –style=css –routing=true –skipGit=trueNext we install the Angular Material by running the following schematicng add @angular/materialLet’s add a navigation component to the application by running the navigation schematicng generate @angular/material:nav navWe can also add a dashboard component using the material schematicng generate @angular/material:dashboard dashboardNext we install the Flex-layout module which is a superior layout engine to assist with the CSS flex-box features:npm install @angular/flex-layout –saveThe next thing is to wire up the @NgRx state management library that lays in the core of our application design.

npm install @ngrx/store, @ngrx/effects, @ngrx/router-store, @ngrx/entity, @ngrx/store-devtools, ngrx-store-freeze –saveTo interact with Ethereum blockchain we will use the Ethers.

js library developed my RicMoo (Richard Moore)npm install ethers –saveThe Root State and the GuardThe application state in NgRx is a single immutable data tree structure.

The state tree will start from the root state once the AppModule is loaded.

The root state is shared globally among all components.

It will then continue to grow in size as more lazily-loaded Angular modules are loaded into the application.

We define our root state interface as follows:It is composed from the router state, the spinner state, the error state and the web3Provider state.

The spinner state is responsible for toggling the display of a loading indicator defined in the loader component.

We manage the spinner state by dispatching the following actions to the store:Notice that we’re using the Action Creator that was recently introduced by Alex Okrushko in his super blog post.

The error state is listening for the action:and it is handled by the side effect:On the side note, there was some very interesting discussion recently about how to properly manage loading or error state in NgRx.

Regarding this topic please check this and this.

The web3Provider root state is where all the fun begins!.It has the following propertiesand is responsible for monitoring the gateway between our DApp and the Ethereum blockchain.

The approach we use closely resembles the idea discussed in the blog written by GrandSchtroumpf.

To be able to communicate with the Ethereum network using MetaMask we need to setup the corresponding ethers.

js Web3 provider.

First we define the tree-shakable InjectionToken MetamaskWeb3Provider and instruct it to inject the Ethereum web3 provider injected by MetaMask windows.

ethereum.

Then, we extend the ethers.

js Web3Provider provider and inject the MetamaskWeb3Provider token into its constructor.

To get access to the user account on blockchain, MetaMask requires that we call enable() method on its native web3 provider.

We manage it in the metaMaskEnable$ effect by listening for the '[Web3/Provider] Init]action.

Here is what is happening behind the scenes.

We introduced the EthInitGuard guard which we built to control the route resolution process.

The guard is observing the metamaskEnable property of the state.

If this value is false, the guard will dispatch the '[Web3/Provider] Init]action to broadcast the request to connect to the Ethereum blockchain.

The biggest benefit of this approach is that we are now in control of the MetaMask’s popup window for user-approved account access.

Once we compile and run the application, it will load our root state and result in the following home page:If we try to navigate to any other route guarded by the EthInitGuard, it will trigger an approval popup from MetaMask asking permission to access the user account.

Icons made by Freepik from www.

flaticon.

com is licensed by CC 3.

0 BYIcons made by photo3idea_studio from www.

flaticon.

com is licensed by CC 3.

0????.Thank you!.Please stay tuned for another articles for this blog series.

Reference:Architecture Ethereum DApp with Angular, Angular Material and NgRx, by Alex YevseyevichAngular NgRx Material Starter, by Tomas TrajanNGRX Store: Understanding State Selectors, by Todd MottoNgRx + Loading Indicator, by Brian LoveNgRx: Action Creators redesigned, by Alex OkrushkoHandling Error States with NgRx, by Brandon RobertsHaving fun with State in Angular, by Christian JankerSmart Contract Escrow DApp — Buyer View, by Jackson NgSmart Contract Escrow DApp — Seller View, by Jackson NgCreating Smart Contracts with Smart Contract, by Jackson NgSolidity Smart Contracts Design Patterns, by Alexander Vitanov5 minute guide to deploying smart contracts with Truffle and Ropsten, by Nicole ZhuRPC Access to Ethereum with Infura, by Jackson NgIPFS and Angular 6, by GrandSchtroumpfEthers and Angular, by GrandSchtroumpfHDWallet with ethers.

js and Angular, by GrandSchtroumpfethers.

js — Version 4.

0 Release, by RicMooBuild an Ethereum DApp Using Ethers.

js, by Mahesh MurthyPlease Follow me on Medium , Twitter or LinkedIn.

????.Special thanks to Mike Gibbons for reviewing this article.

.

. More details

Leave a Reply