0

I am trying to return a dynamic state array full of hashes, using Web.js. Currently the function on the Web3.js side is returning null in the console.log.

Here's my Contract:

pragma solidity >=0.4.21 <0.7.0;
pragma experimental ABIEncoderV2;

contract StoreHash {
 string public ipfsHash;
 string[] public hashes;

 mapping (address => string) public userFiles;
 
 function sendHash(string memory x) public {
   ipfsHash = x;
   hashes.push(x);
   userFiles[msg.sender] = x;

 }

 function getAllHashes() public view returns (string[] memory) {
     
     string[] memory hash_memory = new string[] (hashes.length);
     
     for(uint i = 0; i < hashes.length; i++) {
         hash_memory[i] = hashes[i];
     }
     
     return hash_memory;
 }
}

and here's the function call using Web3.js

import {Table, Container, Button, Form } from 'react-bootstrap';
import React, { Component } from 'react';
import './App.css';
import getWeb3 from './getWeb3';
import Web3 from 'web3';
import ipfs from './ipfs';
import storeHash from './storehash';

class App extends Component {
 
    state = {
      ipfsHash:null,
      buffer:'',
      ethAddress:'',
      blockNumber:'',
      transactionHash:'',
      gasUsed:'',
      web3: '',
      txReceipt: '',
      hashes: new Array()
    };
    
    componentWillMount() {
    // Get network provider and web3 instance.
    // See utils/getWeb3 for more info.
   
    getWeb3
    .then(results => {
      this.setState({
        web3: results.web3
      })

      // Instantiate contract once web3 provided.
      this.instantiateContract()
    })
    .catch(() => {
      console.log('Error finding web3.')
    })
  }
  
   
    captureFile =(event) => {
        event.stopPropagation()
        event.preventDefault()
        const file = event.target.files[0]
        let reader = new window.FileReader()
        reader.readAsArrayBuffer(file)
        reader.onloadend = () => this.convertToBuffer(reader)    
      };

    convertToBuffer = async(reader) => {
      //file is converted to a buffer to prepare for uploading to IPFS
        const buffer = await Buffer.from(reader.result);
      //set this buffer -using es6 syntax
        this.setState({buffer});
    };

    onClick = async () => {

    try{
        this.setState({blockNumber:"waiting.."});
        this.setState({gasUsed:"waiting..."});

        await getWeb3.eth.getTransactionReceipt(this.state.transactionHash, (err, txReceipt)=>{
          console.log(err,txReceipt);
          this.setState({txReceipt});
        }); //await for getTransactionReceipt

        await this.setState({blockNumber: this.state.txReceipt.blockNumber});
        await this.setState({gasUsed: this.state.txReceipt.gasUsed});    
      } //try
    catch(error){
        console.log(error);
      } //catch
  } //onClick

    onSubmit = async (event) => {
      event.preventDefault();

      // Get network provider and web3 instance.
     if (window.ethereum) {
        window.web3 = new Web3(window.ethereum);
        await window.ethereum.enable();
      } else if (window.web3) {
        window.web3 = new Web3(window.web3.currentProvider);
      } else {
        console.log("Non-Ethereum browser detected. You should consider trying MetaMask!");
      }

      //bring in user's metamask account address
      const web3 = window.web3;
      const accounts = await web3.eth.getAccounts();
     
      console.log('Sending from Metamask account: ' + accounts[0]);

      //obtain contract address from storehash.js
      const ethAddress = await storeHash.options.address;
      this.setState({ethAddress});

      //save document to IPFS,return its hash#, and set hash# to state
      await ipfs.add(this.state.buffer, (err, ipfsHash) => {
        console.log(err,ipfsHash);
        //setState by setting ipfsHash to ipfsHash[0].hash 
        this.setState({ ipfsHash:ipfsHash[0].hash });

        storeHash.methods.sendHash(this.state.ipfsHash)
          .send({
            from: accounts[0] 
          }, 
          (error, transactionHash) => {
          console.log(transactionHash);
          this.setState({transactionHash});

          storeHash.methods.hashes(1)
            .call({from: accounts[0]}, 
            (error, hashes) => {
            console.log(hashes);
            this.setState({hashes});

          }); //storehash - getAllHashes  
        }); //storehash - sendHash

      }) //await ipfs.add 
    }; //onSubmit     

I am unsure if:

  1. The state variable push functions is actually adding to the state array? OR
  2. I am calling the function correctly on the Web3 side?

Would greatly appreciate any guidance here....

5
  • To ensure sendHash works generate an event and check the transaction receipt contains the event.
    – Ismael
    Aug 13 at 5:26
  • Thanks I tried this last night and did not see the event details. I confirm that the ipfsHash value is being received. However, there’s no way for me to see if it’s being stored on the blockchain by my contract. Aug 13 at 12:43
  • That's the idea of generating an event in the contract. If the transaction succeeded you'll see the event in the transaction receipt. The receipt also has a status field that indicates if the transaction completed without reverting. If the transaction failed try using estimateGas to determine the gas needed.
    – Ismael
    Aug 13 at 14:26
  • Ok so I narrowed down the issue. I believe the push(x) to the hashes array isnt working properly. I check the size of the array and its zero. Any reason why this is happening? Aug 14 at 17:32
  • What does the transaction's receipt look like?
    – Ismael
    Aug 14 at 18:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.