reactjsblockchainethereumsmartcontractshardhat

Error in the integration between Hardhat and react.js


This error keeps showing up when I try to use react.js to input data in the smart contract using hardhat

ERROR in ./src/BridgeData.js 69:23-52 export 'ethers'.'providers' (imported as 'ethers') was not found in 'ethers' (possible exports: AbiCoder, AbstractProvider, AbstractSigner, AlchemyProvider, AnkrProvider, BaseContract, BaseWallet, Block, BrowserProvider, ChainstackProvider, CloudflareProvider, ConstructorFragment, Contract, ContractEventPayload, ContractFactory, ContractTransactionReceipt, ContractTransactionResponse, ContractUnknownEventPayload, EnsPlugin, EnsResolver, ErrorDescription, ErrorFragment, EtherSymbol, EtherscanPlugin, EtherscanProvider, EventFragment, EventLog, EventPayload, FallbackFragment, FallbackProvider, FeeData, FeeDataNetworkPlugin, FetchCancelSignal, FetchRequest, FetchResponse, FetchUrlFeeDataNetworkPlugin, FixedNumber, Fragment, FunctionFragment, GasCostPlugin, HDNodeVoidWallet, HDNodeWallet, Indexed, InfuraProvider, InfuraWebSocketProvider, Interface, IpcSocketProvider, JsonRpcApiProvider, JsonRpcProvider, JsonRpcSigner, LangEn, Log, LogDescription, MaxInt256, MaxUint256, MessagePrefix, MinInt256, Mnemonic, MulticoinProviderPlugin, N, NamedFragment, Network, NetworkPlugin, NonceManager, ParamType, PocketProvider, QuickNodeProvider, Result, Signature, SigningKey, SocketBlockSubscriber, SocketEventSubscriber, SocketPendingSubscriber, SocketProvider, SocketSubscriber, StructFragment, Transaction, TransactionDescription, TransactionReceipt, TransactionResponse, Typed, TypedDataEncoder, UndecodedEventLog, UnmanagedSubscriber, Utf8ErrorFuncs, VoidSigner, Wallet, WebSocketProvider, WeiPerEther, Wordlist, WordlistOwl, WordlistOwlA, ZeroAddress, ZeroHash, accessListify, assert, assertArgument, assertArgumentCount, assertNormalize, assertPrivate, checkResultErrors, computeAddress, computeHmac, concat, copyRequest, dataLength, dataSlice, decodeBase58, decodeBase64, decodeBytes32String, decodeRlp, decryptCrowdsaleJson, decryptKeystoreJson, decryptKeystoreJsonSync, defaultPath, defineProperties, dnsEncode, encodeBase58, encodeBase64, encodeBytes32String, encodeRlp, encryptKeystoreJson, encryptKeystoreJsonSync, ensNormalize, formatEther, formatUnits, fromTwos, getAccountPath, getAddress, getBigInt, getBytes, getBytesCopy, getCreate2Address, getCreateAddress, getDefaultProvider, getIcapAddress, getIndexedAccountPath, getNumber, getUint, hashMessage, hexlify, id, isAddress, isAddressable, isBytesLike, isCallException, isCrowdsaleJson, isError, isHexString, isKeystoreJson, isValidName, keccak256, lock, makeError, mask, namehash, parseEther, parseUnits, pbkdf2, randomBytes, recoverAddress, resolveAddress, resolveProperties, ripemd160, scrypt, scryptSync, sha256, sha512, showThrottleMessage, solidityPacked, solidityPackedKeccak256, solidityPackedSha256, stripZerosLeft, toBeArray, toBeHex, toBigInt, toNumber, toQuantity, toTwos, toUtf8Bytes, toUtf8CodePoints, toUtf8String, uuidV4, verifyMessage, verifyTypedData, version, wordlists, zeroPadBytes, zeroPadValue)

Here are the scripts used in react.js

  1. BridgeData.js
import { ethers } from "ethers";

const contractAddress = "0x5fc8d32690cc91d4c39d9d3abcbd16989f875707"; // Replace with your contract address
const contractABI = [
  // ABI of the BridgeData contract
  {
    "inputs": [
      {"internalType": "uint256", "name": "bridgeId", "type": "uint256"},
      {"internalType": "string", "name": "name", "type": "string"},
      {"internalType": "string", "name": "location", "type": "string"},
      {"internalType": "uint256", "name": "length", "type": "uint256"},
      {"internalType": "uint256", "name": "height", "type": "uint256"},
      {"internalType": "uint256", "name": "yearBuilt", "type": "uint256"}
    ],
    "name": "addBridge",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [{"internalType": "uint256", "name": "bridgeId", "type": "uint256"}],
    "name": "getBridge",
    "outputs": [
      {"internalType": "string", "name": "", "type": "string"},
      {"internalType": "string", "name": "", "type": "string"},
      {"internalType": "uint256", "name": "", "type": "uint256"},
      {"internalType": "uint256", "name": "", "type": "uint256"},
      {"internalType": "uint256", "name": "", "type": "uint256"}
    ],
    "stateMutability": "view",
    "type": "function"
  }
];

const getBridgeDataContract = () => {
  const provider = new ethers.providers.Web3Provider(window.ethereum);
  const signer = provider.getSigner();
  return new ethers.Contract(contractAddress, contractABI, signer);
};

export { getBridgeDataContract };

  1. BridgeForm.js
import React, { useState } from "react";
import { getBridgeDataContract } from "./BridgeData";

const BridgeForm = () => {
  const [bridgeId, setBridgeId] = useState("");
  const [name, setName] = useState("");
  const [location, setLocation] = useState("");
  const [length, setLength] = useState("");
  const [height, setHeight] = useState("");
  const [yearBuilt, setYearBuilt] = useState("");

  const handleSubmit = async (event) => {
    event.preventDefault();
    const contract = getBridgeDataContract();
    await contract.addBridge(
      bridgeId,
      name,
      location,
      length,
      height,
      yearBuilt
    );
    console.log("Bridge data added successfully!");
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>Bridge ID:</label>
        <input
          type="number"
          value={bridgeId}
          onChange={(e) => setBridgeId(e.target.value)}
          required
        />
      </div>
      <div>
        <label>Name:</label>
        <input
          type="text"
          value={name}
          onChange={(e) => setName(e.target.value)}
          required
        />
      </div>
      <div>
        <label>Location:</label>
        <input
          type="text"
          value={location}
          onChange={(e) => setLocation(e.target.value)}
          required
        />
      </div>
      <div>
        <label>Length (meters):</label>
        <input
          type="number"
          value={length}
          onChange={(e) => setLength(e.target.value)}
          required
        />
      </div>
      <div>
        <label>Height (meters):</label>
        <input
          type="number"
          value={height}
          onChange={(e) => setHeight(e.target.value)}
          required
        />
      </div>
      <div>
        <label>Year Built:</label>
        <input
          type="number"
          value={yearBuilt}
          onChange={(e) => setYearBuilt(e.target.value)}
          required
        />
      </div>
      <button type="submit">Add Bridge</button>
    </form>
  );
};

export default BridgeForm;

  1. BridgeDisplay.js
// BridgeDisplay.js
import React, { useState } from "react";
import { getBridgeDataContract } from "./BridgeData";

const BridgeDisplay = () => {
  const [bridgeId, setBridgeId] = useState("");
  const [bridge, setBridge] = useState(null);

  const handleSubmit = async (event) => {
    event.preventDefault();
    const contract = getBridgeDataContract();
    const bridgeData = await contract.getBridge(bridgeId);
    setBridge({
      name: bridgeData[0],
      location: bridgeData[1],
      length: bridgeData[2],
      height: bridgeData[3],
      yearBuilt: bridgeData[4]
    });
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <div>
          <label>Bridge ID:</label>
          <input
            type="number"
            value={bridgeId}
            onChange={(e) => setBridgeId(e.target.value)}
            required
          />
        </div>
        <button type="submit">Get Bridge Data</button>
      </form>
      {bridge && (
        <div>
          <h2>Bridge Data</h2>
          <p>Name: {bridge.name}</p>
          <p>Location: {bridge.location}</p>
          <p>Length: {bridge.length} meters</p>
          <p>Height: {bridge.height} meters</p>
          <p>Year Built: {bridge.yearBuilt}</p>
        </div>
      )}
    </div>
  );
};

export default BridgeDisplay;

  1. App.js
// App.js
import React from "react";
import BridgeForm from "./BridgeForm";
import BridgeDisplay from "./BridgeDisplay";

function App() {
  return (
    <div className="App">
      <h1>Bridge Data Management</h1>
      <BridgeForm />
      <BridgeDisplay />
    </div>
  );
}

export default App;

I tried the previous scripts and every time I get the same error.


Solution

  • you might have installed ethers v6 but using ethers v5 implementation. From migrating guide

    // v5
    provider = new ethers.providers.Web3Provider(window.ethereum)
    
    // v6:
    provider = new ethers.BrowserProvider(window.ethereum)
    

    and from docs

    let signer = null;
    
    let provider;
    if (window.ethereum == null) {
    
        // If MetaMask is not installed, we use the default provider,
        // which is backed by a variety of third-party services (such
        // as INFURA). They do not have private keys installed,
        // so they only have read-only access
        console.log("MetaMask not installed; using read-only defaults")
        provider = ethers.getDefaultProvider()
    
    } else {
    
        // Connect to the MetaMask EIP-1193 object. This is a standard
        // protocol that allows Ethers access to make all read-only
        // requests through MetaMask.
        provider = new ethers.BrowserProvider(window.ethereum)
    
        // It also provides an opportunity to request access to write
        // operations, which will be performed by the private key
        // that MetaMask manages for the user.
        signer = await provider.getSigner();
    }