0

Currently, when I try to write a function on Solidity Smart Contract from ReactJS, it is not working and throws an error called "unknown account." for the below code.

await contractMethods.methods.functionName(params).send({ from: accounts[0], gas: parseInt(estimatedGas), gasPrice: parseInt(gasPrice) });

After adding the private key of the wallet, which is used to deploy the specific contract, the below code is working.

web3.eth.accounts.wallet.add(config.json.privateKey);
await contractMethods.methods.functionName(params).send({ from: accounts[0], gas: parseInt(estimatedGas), gasPrice: parseInt(gasPrice) });

Once the private key is added, I can access the write function of the Solidity smart contract.

Questions:

  1. Please explain the above method and why we need a private key to access the smart contract for writing or storing values.
  2. Are there any options for accessing the smart contract for writing or storing values without requiring a private key from ReactJS?

1 Answer 1

1
  1. Private key is needed for signing and sending transactions. That's why, you don't need the private key for reading from blockchain, but for writing on blockchain.

    As, when interacting with a blockchain network, particularly when you want to write data (like executing a function on a smart contract), you need to send a transaction to the network. This transaction needs to be signed to prove that it comes from the legitimate owner of the account.

  2. On the frontend of the dApps, the signing of the transactions is done using the signer of the user's wallet that's created from the browser's injected provider using the window.ethereum object.

    Here's the minimal ReactJS code (using web3.js v4.8.0, i.e., the latest version at this point in time) to connect the wallet and call the contract function that requires signing and sending of transaction:

    import React, { useState, useEffect } from 'react';
    import Web3 from 'web3';
    
    // Replace 'MyContractABI' and 'contractAddress' with your actual contract ABI and address
    const MyContractABI = [
    ]; // Your contract ABI
    
    const contractAddress = ''; // Your contract address
    
    function App() {
      const [web3, setWeb3] = useState(null);
      const [isConnected, setIsConnected] = useState(false);
      const [account, setAccount] = useState('');
      const [contract, setContract] = useState(null);
    
      useEffect(() => {
        // Check if MetaMask is installed
        if (window.ethereum) {
          const web3Instance = new Web3(window.ethereum);
          setWeb3(web3Instance);
    
          // Check if user is already connected
          window.ethereum
            .request({ method: 'eth_accounts' })
            .then(accounts => {
              if (accounts.length > 0) {
                setIsConnected(true);
                setAccount(accounts[0]);
              }
            })
            .catch(err => console.error(err));
    
          // Listen for account changes
          window.ethereum.on('accountsChanged', accounts => {
            setIsConnected(accounts.length > 0);
            setAccount(accounts[0] || '');
          });
        } else {
          console.log('MetaMask is not installed');
        }
      }, []);
    
      useEffect(() => {
        if (web3) {
          // Initialize contract instance
          const contractInstance = new web3.eth.Contract(MyContractABI, contractAddress);
          setContract(contractInstance);
        }
      }, [web3]);
    
      const connectWallet = async () => {
        try {
          const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
          setIsConnected(true);
          setAccount(accounts[0]);
        } catch (error) {
          console.error(error);
        }
      };
    
      const callContractFunction = async () => {
        try {
          // Send the transaction
          const transaction = await contract.methods.yourContractFunction().send({ from: account });
    
          // Get the transaction hash from the receipt
          const receipt = await web3.eth.getTransactionReceipt(transaction.transactionHash);
    
          const txHash = receipt.transactionHash;
    
          alert(`Function call is successful.\n\nTransaction Hash: ${txHash}`);
        } catch (error) {
          console.error('Error calling contract function:', error);
        }
      };
    
      return (
        <div>
          {!isConnected ? (
            <button onClick={connectWallet}>Connect Wallet</button>
          ) : (
            <div>
              <p>Wallet Connected</p>
              <p>Connected Address: {account}</p>
            </div>
          )}
          {!isConnected ? (<div></div>) : <button onClick={callContractFunction}>Call Contract Function</button>}
        </div>
      );
    }
    
    export default App;
    
2
  • 2
    That works! Thanks for the explanation and code snippet!
    – AIT DEV
    Commented Apr 20 at 16:41
  • You’re welcome, @AITDEV. Glad to help. Commented Apr 20 at 17:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.