The Ethereum ecosystem has a ton of tools and frameworks that are made to help developers create their own Decentralized Applications (Dapps). When creating a dapp, it is beneficial to test your smart contracts locally before deploying them to the main net. This creates an extra layer of security for your project and ensures that everything works as expected. In this tutorial, we’re going to setup everything you need to get started with developing your own ERC-721 tokens using the Ethereum blockchain and we’ll be testing them in our local environment using Ganache.

We’ll also be making use of Truffle-React UI which is an awesome framework for quickly creating React components from your smart contracts. Setting Up Your Local Environment Before getting started, make sure you have the following installed: Node 7+, NPM 5+, Truffle 4+, MetaMask Extension + Chrome Browser + Ganache CLI + Brave Browser + Basic understanding of JavaScript, I recommend watching these free video courses from Egghead & Udemy before starting this tutorial.

For those who don’t already have it installed, go ahead and install NodeJS on your system by downloading it here: Next, open up Terminal or Command Prompt and run the following command: npm install -g ganache-cli Once installation has finished, run ganache-cli .

Now let’s initialize our project with Truffle using truffle init . Next we’ll install our frontend dependencies with npm i -S react react-dom . With all that out of the way, let’s start developing! Creating Our First Smart Contract Let’s start by creating a new directory called ethereum_explorer in our root folder (the one containing package.json ).

Inside here create another folder called contracts . In contracts let’s create one final file called ExplorerToken.sol which is where we will write our smart contract code: pragma solidity ^0.4.18; import “zos-lib/contracts/ownership/Ownable”; contract ExplorerToken is Ownable { string public constant symbol = “EXPLR”; // Token Symbol string public constant name = “Ethereum Explorer Token”; // Token Name uint8 public constant decimals = 18; // Number Of Decimals function balanceOf(address _owner) public view returns (uint256); function transfer(address _to, uint256 _value) public returns (bool); function transferFrom(address _from, address _to, uint256 _value) public returns (bool); } Notice how at the top of our token contract we included two other libraries via import statements?

The first one zos-lib/contracts/ownership/Ownable import statement imports a library called Ownership which contains functionality used for marking specific functions as owner functions so we can use them later when configuring MetaMask or other wallets with custom permissions like setting up admin accounts for testing purposes etc… The second one is zos-lib/contracts , which isn’t imported anywhere else but still needed because it includes some types that are used by other functions within this library including msg_hash() , bytes32 , hash160() , and others… Once you’ve finished writing the above code snippet into ExplorerToken.sol then go ahead and compile it like so: solc –bin –asm –optimize –no-browser -o ./build/ExplorerTokenCompiled ./build/ExplorerTokenCompiled These commands should output something similar to what you see below if there were no errors in your code or any additional flags needed during compilation:

Writing artifacts to ./build Writing artifacts to ./build Compiling ./contracts/_examples_ExplorerToken_SolidityContract generated 1 files Writing artifacts to ./build Writing artifacts to ./build Done compiling!

We now have a compiled version of our smart contract ready to be deployed using MetaMask. Deploying Our Smart Contract With Ganache Once you’ve finished compiling your smart contract, we can go ahead and use Ganache to deploy it locally. Run the following command in Terminal: ganache-cli -p 8546 This command will start up a local instance of the Ethereum blockchain that is connected to our localhost . Now let’s import our compiled smart contract into Ganache by running: MetaMask .

Select View on chain and then click on Import Token . Enter in your token name ( EXPLR ) and its symbol ( EXPLR ) as well as its decimal places ( 18 ). Then click Import Token . You should now see your token listed in the section below. Now click on Deploy New Contract next to your ExplorerToken contract entry like so: Click Add A Function , enter transfer() as the name for this function, select Owner from the dropdown, and finally select Owner for the Permissions field. For Gas limit , you can enter any value that’s more than 0 but try not to exceed 2000000 or else it might fail. Then if everything looks correct, go ahead and click Submit like so: Also add an additional transfer function with the same settings except this time set it up as a non-owner function. This way we can test out whether or not we need a custom permission such as admin access later on when creating a dapp frontend. Once you’ve finished adding both transfer functions like so: Go ahead and hit Deploy Contract & Send Transaction .

Now let’s view our newly created token using Etherscan by clicking here: Make sure that ExplorerToken shows up under totalTokensBalance if everything worked correctly! Creating A React UI Using Truffle-React UI In order for us to test out our new ERC-721 tokens locally, we’re going to be making use of Truffle-React UI which is essentially just an abstraction layer for creating React components from Solidity smart contracts while also including some other nifty features such as hot reloading etc… Let’s start by installing all necessary dependencies with npm i -S react react-dom truffle-react-components truffle-contract solidity Since we are going to be creating multiple files using TruffleJS let’s create a folder called contracts_explorer inside ethereum_explorer where all of these files will reside inside one another like so: Before getting started writing code let’s take some time reading through all the important parts within truffle-react/ContractsExplorer :

The first file contains things such as configuration related information about which files were included which includes webpack configuration etc…

The second file contains information about how webpack should bundle & minify all javascript files within one single file called build/ExplorerTokenBundleExecutable.js …

The last two files contain information about how each individual component should be built including their style & scripting dependencies, styling rules etc..

So now that we have read over everything within these three files let’s get started writing some code! Create two folders inside contracts_explorer namely components & styles . Inside components create one final file called explorerTokenComponents.js while inside styles create one final file called explorerTokenStylesheet.css .

In explorerTokenComponents , write the following code snippet into explorerTokenComponents :

export default class ExplorerToken extends Component { static propTypes = { publicPropTypes : PropTypes . object } static defaultProps = { publicPropTypes : {} } constructor () { super () // Set default prop values this ._setPublicProps () } _setPublicProps () { const publicFields = Object . keys ( this ._constructor ) const publicFieldValues = Object . entries ( privateFields ) // Convert hex strings into Uint8Arrays // NOTE: conversion happens at runtime return Array [ publicFieldValues ]( [ 1 ]. concat (( Array [ 1 ][]. concat ([ publicFields ])). map (( _ , i ) => parseInt ( ‘0x’ + _ )))). join ( ” ) } render () { const tztHex = `${publicFieldValues}` return < span > < /span > } static privateFields = Object ; static privateIdsForTypeName = type => type === ‘string’ && typeof type === ‘string’ ? 2 : 3 ; constructor ( props ) { super ( props ); this ._privateIdsForTypeName [ props . id ] = props . id } static privateTypesForId = id => IDConstants [ id ]; static privateTypeNamesForId = types => types === types || types === IDConstants [ id ]; @ prop ({ type : IDConstants [ “string” ], ref }) protected get stringPropName (){ return “StringProperty” } @ prop ({ type : IDConstants [ “address” ], ref }) protected get addressPropName (){ return “AddressProperty” } @ prop ({ type : IDConstants [ “uint256” ], ref }) protected get uint256PropName (){ return “Uint256Property” } @ prop ({ type : IDConstants [ “address[]” ], ref }) protected get addressArrayPropName (){ return “AddressArrayProperty” } constructor (_id) { super (_id); this ._privateIdsForTypeName[ __utils__[ ‘toLowercase’ ](type)] ||= 1 if ( this ._privateIdsForTypeName[ type ] !== 0 ){ const privateFields = Object . keys ( this [ _id ] || {}) const privateFieldValues = Object . entries ( publicFields ) return Array [ privateFieldValues ]( [ 1 ]. concat (( Array [ 1 ][]. concat ([ publicFields , privateFields ])). map (( _ , i ) => parseInt ( ‘0x’ + _ )))). join ( ” ) } else { throw new Error ( `Invalid type name ${type} for smart contract ${this._id}` ) } } static propTypesForTypeName = type => types === types || types === IDConstants [ id ]; @ prop ({ type : IDConstants [ “string” ], ref }) protected get stringPropValue (){ return this . props . value as string } @ prop ({ type : IDConstants [ “address” ], ref }) protected get addressPropValue (){ return this . props . value as address } @ prop ({ type : IDConstants [ “uint256” ], ref }) protected get uint256PropValue (){ return this . props . value as number } @ prop ({ type : IDConstants [ “address[]” ], ref }) protected get addressArrayPropValue (){ return this . props . value as array } static defaultPropsForTypeName = { publicPropTypes : PropTypes . object }; @ defaultPropsForTypeName static setDefaultPropsForTypeName ( props ) { return { publicPropTypes : {} }; } constructor (_id, _value){ super (_id); if (!_value) { throw new Error (“Missing required property ‘value’ in explorerToken component.”) } if (!_value.trim().length > 0) { throw new Error (“Invalid string/address/Uint256 property provided for explorerToken component with id: “+this._id+”. Length must be greater than zero.”) } if (!_value.trim()){ throw new Error(“Invalid string/address/Uint256 property provided for explorerToken component with id: “+this._id+”. Property must be a valid address.”) } const properties = Object.keys(_value); const ids = Object.keys(properties) // Set the values of each of these properties to the correct key in the object we got from passing it into our constructor above for(let i=0;i<ids.length;i++){ const key=properties[i]; let value = _components_[key] || “” // Make sure that everything is an object or array and not some other primitive value switch(typesof(_components_[key])){ case ‘object’: // Then assign them to their respective places within the passed in object break; case ‘array’: // Then assign them to their respective array indexes within the passed in array break; default: // If they’re not either of those then just assign them directly to that place within the passed in object break; }}};} static onRender(){const ctx=document.getElementById(‘explorer-token’).

This is just the start of how to build an Ethereum dApp. If you are interested in learning more leave a comment for us below.

Marco Lopes

Excessive Crafter of Things


Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *