1

Weird question, so I have created a smart contract, verified that it works, even deployed it using Web3, Metamask and HTML/Javascript. I understand that worked.

Now I am trying to integrate it into some front end a group member made. The problem is that I cannot call the function. I have verified that Web3 is injected into my code, since I can see my Metamask address in the log, I am just unable to actually call the function or prompt Metamask. I am at a loss since previously, I was calling the function through a script, which occurred on button click. But on this workflow, things are rendered back to back without a click. I just need some guidance on where I can put my contract script.

import React, { Component } from "react";
import {
  FormGroup,
  FormControl,
  ControlLabel
} from "react-bootstrap";
import LoaderButton from "../components/LoaderButton";
import "./Sub.css";
import Web3 from 'web3';
import Web3Provider from 'react-web3-provider';

export default class BugSub extends Component {
  constructor(props) {

    const web3 = new Web3(Web3.givenProvider || "http://localhost:8545");
    web3.eth.getAccounts().then(console.log);  //this here prints out my primary MetaMask address

    super(props);
    this.state = {
      sum: "",
      fullissue: "",
      images: "",
      matrix: "",
      newSub: null
    };
  }



  validateForm() {
    return (
      this.state.company.length > 0 &&
      this.state.images.length > 0 &&
      this.state.images === this.state.matrix
    );
  }


  handleChange = event => {
    this.setState({
      [event.target.id]: event.target.value
    });
  }

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


    this.setState({ isLoading: true });

    this.setState({ newSub: "test" });

    this.setState({ isLoading: false });
  }


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

    this.setState({ isLoading: true });
    var senderAccount;
    web3.eth.getAccounts((error, accounts) => (senderAccount = accounts[0]));

    console.log(senderAccount);


    var Contract = new web3.eth.Contract(ABI, '0x0982008ea0509fb05283eeba2ff161a5964a67b0', {
  from: senderAccount});

    window.contractInstance = Contract;

    window.contractInstance.methods.actualContractMethod("value a", "valueb").send({from: senderAccount}).on('transactionHash',            function(hash){ console.log("Hash: " + hash);  

  }

  renderSubmissionForm() {
    return (
      <form onSubmit={this.handleSubmissionSubmit}>
        <LoaderButton
          block
          bsSize="large"
          type="submit"
          isLoading={this.state.isLoading}
          text="Return home"
          loadingText="Thank you…"
        />
      </form>
    );
  }

  renderForm() {
    return (
      <form onSubmit={this.handleSubmit}>
        <FormGroup controlId="company" bsSize="large">
          <ControlLabel> Company</ControlLabel>
          <FormControl
            autoFocus
            type="company"
            value={this.state.company}
            onChange={this.handleChange}
          />
        </FormGroup>

        <FormGroup controlId="sum" bsSize="large">
          <ControlLabel>Summary</ControlLabel>
          <FormControl
            autoFocus
            type="sum"
            value={this.state.sum}
            onChange={this.handleChange}
          />
        </FormGroup>
        <FormGroup controlId="fullissue" bsSize="large">
          <ControlLabel> Statement </ControlLabel>
          <FormControl as="textarea" rows="10" type="fullissue" value={this.state.fullissue} onChange={this.handleChange}
          />
        </FormGroup>
        <FormGroup controlId="images" bsSize="large">
          <ControlLabel>Images</ControlLabel>
          <FormControl
            value={this.state.images}
            onChange={this.handleChange}
            type="images"
          />
        </FormGroup>
        <FormGroup controlId="matrix" bsSize="large">
          <ControlLabel> Intensity</ControlLabel>
          <FormControl
            value={this.state.matrix}
            onChange={this.handleChange}
            type="matrix"
          />
        </FormGroup>
        <LoaderButton
        onclick="activate()"
          block
          bsSize="large"
          disabled={!this.validateForm()}
          type="submit"
          isLoading={this.state.isLoading}
          text="Submit"
          loadingText="Submitting..."
        />
      </form>
    );
  }
  render() {
    return (
      <div className="Submission">
        {this.state.newSub === null
          ? this.renderForm()
          : this.renderSubmissionForm()}
      </div>
    );
  }
}

My previous script that called prompted Metamask and deployed the contract was the following

<script>
    if (typeof web3 !== 'undefined') {
        web3 = new Web3(web3.currentProvider);
    } else {
        web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"));
    }
    var senderAccount;
    web3.eth.getAccounts((error, accounts) => (senderAccount = accounts[0]));

    var Contract = new web3.eth.Contract(ABI, 'contractAddress', {from: senderAccount});

    window.contractInstance = Contract;
//activate() was the button
    async function activate() {
        window.contractInstance.methods.actualContractMethod("value a", "valueb").send({from: senderAccount}).on('transactionHash',            function(hash){ console.log("Hash: " + hash);
            });
    }
</script>

The second script worked and prompted MetaMask because the function was invoked on a button click.

There is no button click on the React code, just events. I tried to force the code under the HandleSubmissionSubmit function, but does not run. Metamask is never prompted. Any pointer in the right direction would be very helpful. I have tried everything I know trying to get this to work.

Some quick additional info, the contract should be created when the Loaderbutton is clicked. But the Loaderbutton is clicked twice to change views, once to submit and once to show a Submit loading screen,which is confusing me even more. But that doesn't really matter, I just want to invoke Metamask correctly. I can figure that out myself.

4
  • 1
    HandleSubmissionSubmit does not contain any code to interact with smart contract. Mar 25, 2019 at 6:02
  • Yes. I removed it because wherever I placed it, it would not be invoked. It is very similar to my the script I placed second, but it would never be explicitly because there is no (button) directly invoking it. I can edit the code with a previous example if you would like.
    – memphis
    Mar 25, 2019 at 15:11
  • Wherever you are calling function of web3 place ‘await’ keyword. Mar 25, 2019 at 16:35
  • Ok then let me write the answer, and please accept as working answer so in future if someone get problem can have idea. Mar 26, 2019 at 0:20

1 Answer 1

1

The problem lies here in the handleSubmissionSubmit function. The web3 functions are almost all asynchronous so if you do not write callback or await it will not get the value. For example in this line of code:

var Contract = new web3.eth.Contract(ABI, '0x0982008ea0509fb05283eeba2ff161a5964a67b0', {
      from: senderAccount});

The Contract instance will not get instance back from web3 and will start calling the next statement and in the next call Contract is not pointing to the contract as you think.

To solve this issue, try to write await in all function calls of web3. something like this:

 var Contract = await new web3.eth.Contract(ABI, '0x0982008ea0509fb05283eeba2ff161a5964a67b0', {
      from: senderAccount});

I hope this will resolve your issue.

Your Answer

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

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