DEV Community

loading...
Cover image for The Complete Guide to Full Stack Ethereum Development

The Complete Guide to Full Stack Ethereum Development

Nader Dabit on April 09, 2021

Building Full Stack dApps with React, Ethers.js, Solidity, and Hardhat The code for this project is located here. The video course for ...
Collapse
horaceshmorace profile image
Horace Nelson

Any idea why getBalance in App.js would throw

Error: call revert exception (method="balanceOf(address)", errorSignature=null, errorArgs=[null], reason=null, code=CALL_EXCEPTION, version=abi/5.1.0)

sendCoins works fine.

Collapse
horaceshmorace profile image
Horace Nelson • Edited

Here's the deploy output:

Starting: scripts/deploy.js --network localhost
Deploying contracts with the account: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
Deploying a Greeter with greeting: Hello, World!
Greeter deployed to: 0x5FbDB2315678afecb367f032d93F642f64180aa3
Token deployed to: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512
Enter fullscreen mode Exit fullscreen mode

And here's my App.js:

import './App.css';
import { useState } from 'react';
import { ethers } from 'ethers'
import Greeter from './artifacts/contracts/Greeter.sol/Greeter.json'
import Token from './artifacts/contracts/Token.sol/Token.json'
const greeterAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3"
const tokenAddress = "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512"

function App() {
  const [greeting, setGreetingValue] = useState()
  const [userAccount, setUserAccount] = useState()
  const [amount, setAmount] = useState()

  async function requestAccount() {
    await window.ethereum.request({ method: 'eth_requestAccounts' });
  }

  async function fetchGreeting() {
    if (typeof window.ethereum !== 'undefined') {
      const provider = new ethers.providers.Web3Provider(window.ethereum)
      console.log({ provider })
      const contract = new ethers.Contract(greeterAddress, Greeter.abi, provider)
      try {
        const data = await contract.greet()
        console.log('data: ', data)
      } catch (err) {
        console.log("Error: ", err)
      }
    }    
  }

  async function getBalance() {
    if (typeof window.ethereum !== 'undefined') {
      const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' })
      console.log({ account }) // outputs { account: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" }
      const provider = new ethers.providers.Web3Provider(window.ethereum);
      const signer = provider.getSigner()
      const contract = new ethers.Contract(tokenAddress, Token.abi, signer)

      // THIS THROWS
      contract.balanceOf(account)
        .then(data => {
          console.log("data: ", data.toString())
        })
    }
  }

  async function setGreeting() {
    if (!greeting) return
    if (typeof window.ethereum !== 'undefined') {
      await requestAccount()
      const provider = new ethers.providers.Web3Provider(window.ethereum);
      console.log({ provider })
      const signer = provider.getSigner()
      const contract = new ethers.Contract(greeterAddress, Greeter.abi, signer)
      const transaction = await contract.setGreeting(greeting)
      await transaction.wait()
      fetchGreeting()
    }
  }

  async function sendCoins() {
    if (typeof window.ethereum !== 'undefined') {
      await requestAccount()
      const provider = new ethers.providers.Web3Provider(window.ethereum);
      const signer = provider.getSigner()
      const contract = new ethers.Contract(tokenAddress, Token.abi, signer)
      contract.transfer(userAccount, amount).then(data => console.log({ data }))
    }
  }

  return (
    <div className="App">
      <header className="App-header">
        <button onClick={fetchGreeting}>Fetch Greeting</button>
        <button onClick={setGreeting}>Set Greeting</button>
        <input onChange={e => setGreetingValue(e.target.value)} placeholder="Set greeting" />

        <br />
        <button onClick={getBalance}>Get Balance</button>
        <button onClick={sendCoins}>Send Coins</button>
        <input onChange={e => setUserAccount(e.target.value)} placeholder="Account ID" />
        <input onChange={e => setAmount(e.target.value)} placeholder="Amount" />
      </header>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode
Collapse
dabit3 profile image
Nader Dabit Author

Hey, not sure why you would run into that, did you figure it out?

Thread Thread
dominicwong profile image
Dominic Wong

I am running into the same issue

Thread Thread
dominicwong profile image
Dominic Wong

It worked when I called balanceOf inside deploy.js, just not when calling from App.js

Thread Thread
enemycnt profile image
Nikolay

Stuck with the same issue. After some deep dive into hardhat docs finally, I've found the cause.
It looks like instead

npx run scripts/deploy.js --network localhost
Enter fullscreen mode Exit fullscreen mode

should be

npx run hardhat scripts/deploy.js --network localhost
Enter fullscreen mode Exit fullscreen mode

@dabit3 could you please correct it?

Collapse
richardmelko profile image
Richard Melkonian

I had this error after switching to live test nets then back to local host. The error originates from these line of code in your react components.

const greeterAddress = "{address that you copied in from the local node instance}"

const tokenAddress = "{address that you copied in from the local node instance}"

If you're deploying on Ropsten for example, you will need to manually update this line of code, changing the address to the deployed address that hardhat will supply in the terminal after successfully deploying. So when switching from local to test net, this line needs to be changed!

Collapse
niroshans profile image
Niroshan Sooriyakumar • Edited

Not sure if this will help but I had the same error while working on my own project. I used this blog post as a starting point and my code is slightly different but I was also getting this error on a read-only transaction. The code was working the day before and I was really consued.

After some failed googling, I saw that metamask was still pointing to mainnet (I had switched away from localhost to mainnet later that day). After switching back to localhost things just started working!

Not sure if this will help your particular issue but thought I'd post this here if someone else is also googling this error. Hopes this helps someone out there!

Collapse
gautham profile image
Gautham 🌶

Hi Horace, I was getting this same error - my issue was that I had re-deployed my contracts and their addresses had changed, so I had to copy-paste the new addresses to the top of App.js.

Collapse
emanuel_hodl profile image
Emanuel • Edited

If you have this problem at the beginning:

**Is because you're using an account address instead of the contract address that was prompted in the terminal when you deployed it.

Error:  Error: network does not support ENS (operation="ENS", network="unknown", code=UNSUPPORTED_OPERATION, version=providers/5.1.0)
    at Logger.makeError (index.ts:205)
    at Logger.throwError (index.ts:217)
    at Web3Provider.<anonymous> (base-provider.ts:1407)
    at Generator.next (<anonymous>)
    at fulfilled (base-provider.ts:2)```


Enter fullscreen mode Exit fullscreen mode
Collapse
wschwab profile image
wschwab

I usually get that when I put in a signer instead of the signer's address. The basic idea is that you're putting in something other than a hex address, so the compiler's first thought is that it must be an ENS address (ENS addresses are a way to attach a url-like identifier to an address, like vitalik.eth).

Collapse
nmassi profile image
Nico • Edited

or if you leave "your-contract-address" as I forgot to change the const :)
Looks like any string (if it isn't a contract address) assume it's an ens domain.

Collapse
mayassalman profile image
mayas salman

thank you Nader
I will consider this as my first step to blockchain domain
all the best

Collapse
nmassi profile image
Nico

Nice run Nader – thanks for this.
I am a newbie in Ethereum and I got this error after make some tx with the same account:

Nonce too high. Expected nonce to be 0 but got 4. Note that transactions can't be queued when automining.

If you got this, I figured that there is a limit (I think it's 4 per block) on the number transactions the same address can have on the transaction pool, so just by adding another account in metamask works again :)

Collapse
dabit3 profile image
Nader Dabit Author

Good call out. You can also go to advanced settings and reset the account which will fix this as well.

Collapse
lpatipat profile image
lpatipat

Hi Nader,

Likewise, thanks for this great post. I had the same issue and did resolve it using the methods above. Could you elaborate further on the problem here? Is this just a quirk for the hardhat local network or is this something related to ethereum in general?

Thanks in advance.

Collapse
preciouschicken profile image
Precious Chicken

Great run though, thank you. Do you have any particular reason for preferring hardhat over ganache / truffle? I think the latter is probably more popular (?), not of course that is any reason to prefer it. I hadn't heard of hardhat previously, so will give it a whirl.

I too prefer ethers to web3; I liked the documentation more. Often with these choices though, you just have to choose and go. Otherwise you can spend your entire time choosing rather than actually coding...

Collapse
dabit3 profile image
Nader Dabit Author

I think either are good choices, but after talking with a few people in the space and hearing that some projects like Aave, Decentraland, PoolTogether, Synthetix, and others were now using it I decided to go with Hardhat.

Collapse
preciouschicken profile image
Precious Chicken

Hmmm, interesting. I will defo take a look next time.

Collapse
nirajkamdar profile image
Niraj Kamdar • Edited

I am a long-time truffle user but planning to switch over hardhat for a couple of reasons. In hardhat, you have support for multiple solidity compilers simultaneously, it's really helpful say if you have a 0.5 and 0.8 contract in the same codebase. Truffle will refuse to compile and you have to perform some hacks to make it work. Hardhat also has this nice collection of extensions like: console.log, auto compile & deployment while solidity code changes, etc. which are super useful while developing. I also found some minor problems in the truffle development chain like they set a hard block limit which is lesser than the main net limit which may result in your transaction being reverted.

Collapse
preciouschicken profile image
Precious Chicken

console.log would be very useful...

Collapse
horaceshmorace profile image
Horace Nelson • Edited

Wow. This is the best full-stack dApp tutorial I've seen. I wish I had this a few months ago (before I already learned it). The only thing I think is really missing for a starter tutorial (in a future post maybe?) is to touch on ERC standards. But really, well done.

Collapse
dabit3 profile image
Nader Dabit Author

Thanks Horace, I now plan on updating this with more info based on feedback I've received and also doing a part two that goes into more depth, I appreciate your feedback 🙏

Collapse
thasquirrie profile image
Zulu™#July25th

Can't wait for it. Thanks Nader. One more question tho. I'm a backend dev with Node.js and I'd love to get started with blockchain how and what resources should I get started with. Thanks

Collapse
bdougieyo profile image
Brian Douglas

This is such a great run-through on such a complex topic. I was aware of a lot of these tools but never leveraged them because of how dense the docs and content usually are. I am looking forward to learning more about this space from you. Keep it up!

Collapse
dabit3 profile image
Nader Dabit Author

Thanks Brian, happy to hear this 🙏

Collapse
robertosnap profile image
Collapse
ramvi profile image
Jon Ramvi

Thanks for the perfectly detailed introduction to dapp development!

How do you feel about the hardhat-react plugin? Is that something that could be included in this guide? npmjs.com/package/@symfoni/hardhat...

It autogenerates typed React hooks integrated into the Hardhat smart contract watch pipeline and gives you hot reloading while developing contracts

Collapse
elm3nt0r profile image
elm3nt0r

So symfoni makes it easier to connect the back-end dapp code (eg. the smart contract) to the front-end? So for example, wanted to make a website the will result in exchanging an NFT for ether, symfoni would make it easier?

Collapse
ramvi profile image
Jon Ramvi

That's right. Symfoni, together with Hardhat, does all the heavy lifting and repetitive tasks for you.

Collapse
chiranz profile image
Chiranjibi Poudyal

I am doing this project in typescript, when I run "npx hardhat node" it throws an error saying

An unexpected error occurred:

/home/chiranz/programming/blockchain/smartcontracts/tutorials/react-dapp/hardhat.config.ts:12
export default config;

SyntaxError: Unexpected token 'export'
Enter fullscreen mode Exit fullscreen mode

What am I missing here ?

import { HardhatUserConfig } from "hardhat/types";
const config: HardhatUserConfig = {
  solidity: {
    compilers: [{ version: "0.8.3", settings: {} }],
  },
  paths: { artifacts: "./src/artifacts" },
  networks: {
    hardhat: {
      chainId: 1337,
    },
  },
};

export default config;
Enter fullscreen mode Exit fullscreen mode
Collapse
nicebardo profile image
niceBardo

This is n awesome tutorial, thanks!
I am stuck while trying to set the greeting, I have this error in my console:

Object { code: -32603, message: "Error: [ethjs-query] while formatting outputs from RPC '{\"value\":{\"code\":-32603,\"data\":{\"code\":-32602,\"message\":\"Trying to send an incompatible EIP-155 transaction, signed for another chain.\"}}}'" }

and this in my terminal:

eth_blockNumber (2)
eth_sendRawTransaction

Trying to send an incompatible EIP-155 transaction, signed for another chain.

Can anybody help?
Thanks!

Collapse
a_regularjeff profile image
Jeff • Edited

Verify your hardhat.config.js, in my case my issue was a typo around network

Collapse
charles_lukes profile image
Son DotCom 🥑💙

I had this error too, I resolved it by connecting my meta mask, you'll see the connect button on meta mask click on it.

Collapse
brianfakhoury profile image
Brian Fakhoury

This was great -- really enjoyed the walkthrough.

I'm running into an issue where the deployed contract addresses have already been used previously. What's a straightforward way to force the contract to deploy to another address? I tried changing the solidity files slightly and re-compiling them, but no luck.

Collapse
dominicwong profile image
Dominic Wong

I did the same thing and no luck as well. Tried restarting the node and the contracts were deployed to the same address.

Collapse
mwarger profile image
Mat Warger

I wasn't able to send myself any test ether using the link provided, but I was able to find another way to get some. If you go to MetaMask for the Ropsten test account and hit the "Buy" button, it will give you the option for a test faucet at the bottom of the panel. You can click that button and it will direct you to a webpage that will let you send some test ether to your account - it even fills in the address for you.

button image

Collapse
camerenisonfire profile image
Cameren Dolecheck

Thank you for this well done tutorial. I've done a few tutorial dapps from Dapp University's guides. Those all use Ganache, so it was cool finding this one that used Hardhat. Hardhat feels more streamlined and easier to use.

I look forward to going through your other blockchain tutorials.

Collapse
steadylearner profile image
Steadylearner • Edited

I wrote a blog post "How to make a fullstack dapp with React, Hardhat and Ethers js" following this.

You will have the React frontend examaple along with it.

cover

Collapse
huudyy profile image
PabloHoudini • Edited

Great job!

I am also trying to deploy such full stack react application to fleek, but the problem I have is that artifacts folder is in .gitignore so I do not have access to it like I do in the local environment:

import Election from '../../artifacts/contracts/Election.sol/Election.json'; 
Enter fullscreen mode Exit fullscreen mode

From hardhat docs it is recommended NOT to add that folder as it might get HUGE...
Has someone tried that, maybe ?
any help appreciated;)
~~~~~~~~~!!!UPDATE!!!!~~~~~~~
So, on fleek.co you can actually run 'npx hardhat compile' to create artifact directory for you and make the above import work correctly again, something like this:
alt text

Collapse
ricardo85x profile image
Ricardo T

With truffle the contract address was inside the artifact file on networks.
Are there something like that on hardhat?

I'm asking that, because it is easier to import the address direct from the json file.

Collapse
parkerproject profile image
Parker

Great read. I will do some reading on Crypto, etc. then I can give this a go

Collapse
kp1129 profile image
Katya Pavlopoulos

Thank you so much for putting this guide together!!

Collapse
d4mr profile image
Prithvish Baidya

Extremely well written. Great job!

Collapse
pollock profile image
Tristan Pollock

LOVE IT!

Collapse
alejandrowebdev profile image
Ale

This is amazing. Thanks a lot.

Collapse
safoo profile image
Sarfaraz Rydhan

Thank you for putting this together. Really easy to follow.

Collapse
muzammilaalpha profile image
muzammilaalpha

Good one!

Collapse
herrbertling_13 profile image
Markus Siering

If anyone is interested in using this setup with Vue3/Vite: I've taken this tutorial and made a very simple Vue setup for it :) github.com/HerrBertling/simple-vit...

Collapse
workerphoto profile image
photo worker

Thanks for the article...this is very good content ..write continue and inform me. If you interested in clippingpath APT contact our site.

Collapse
filatovv profile image
Yuri Filatov

Cool! This is a really informative article. Thank you

Collapse
tysonwynne_ profile image
Tyson Wynne

The Ropsten Ethereum Faucet said I was spamming, so I just ended up using this one instead -- faucet.dimensions.network/

Collapse
odoenet profile image
Rene Rubalcava

Nice one! I've been using ganache and truffle, hadn't seen hardhat, I'll be giving this one a shot!

Collapse
metashaker profile image
emilianopb92

Amazing post, a good first approach into one technical implementation of ethereum

Collapse
jsur profile image
Julius Suominen

Really nice, thanks. Easy to follow and informative.

Collapse
fautendy profile image
Fau • Edited

I am having a problem where the metamask wallet is no connecting to the ethers . I cant seem to find where the error is. Please help

Collapse
angelsandoval1 profile image
AngelSandoval1

What solidity extensions do you use for vs code

Collapse
tochman profile image
Thomas Ochman

Hi. Worked my way through the guide in a stream. Great work Nader. Missed the testing part though... Will there be more? youtu.be/xBrPSiapAc8?t=404

Forem Open with the Forem app