3

i am trying to build a simple app (will improve once i get the simple one to work)I created a new Reactapp, added both the contracts and migrations directories and i use ganache and metamaks. I have truffle installed. and i can successfully compile and migrate my contact on ganache

The Dapp has an input field that takes a string and save in bolckchain and then fetch it back and diplay that on screen.

I get an error form this part.

import SimpleStorageContract from '../build/contracts/SimpleStorage.json'

/src/App.js

Module not found: You attempted to import ../build/contracts/SimpleStorage.json which falls outside of the project src/ directory. Relative imports outside of src/ are not supported. You can either move it inside src/, or add a symlink to it from project's node_modules/.

And if i move build/contracts directory into src i get the following error

TypeError: Cannot read property 'set' of undefined

full code:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
//import SimpleStorageContract from '../build/contracts/SimpleStorage.json'
import SimpleStorageContract from './build/contracts/SimpleStorage.json'
import getWeb3 from './utils/getWeb3'
import truffleContract from "truffle-contract";
class App extends Component {


    constructor(props) {
        super(props)

        this.state = {
            account: null,
            web3: null,
            firstName:null,
            fName:null,
        }
    }

    componentWillMount() {

    getWeb3.then(results => {
    this.setState({ web3: results.web3

    })

        this.instantiateContract()
    })
        .catch(() => {
    console.log('Error finding web3.')
        })
    }

    instantiateContract() {
    /*
     * SMART CONTRACT EXAMPLE
     *
     * Normally these functions would be called in the context of a
     * state management library, but for convenience I've placed them here.
     */

    const contract = require(truffleContract)
    const simpleStorage = contract(SimpleStorageContract)
    simpleStorage.setProvider(this.state.web3.currentProvider)

    // Get accounts.
    this.state.web3.eth.getAccounts((error, accounts) => {
        simpleStorage.deployed().then((instance) => {
            this.simpleStorageInstance = instance;
            this.setState({ account: accounts[0] });
            // Get the value from the contract to prove it worked.
            return this.simpleStorageInstance.get.call(accounts[0])
        })
    })
}
      handleSubmit = ()=> {

          const response = this.simpleStorageInstance.get().call();
          this.setState({fName: response.c[0]});
      }






    handleChange = (event)=> {
        const value = event.target.value;

        this.simpleStorageInstance.set(value , {from: this.state.account}).then((r) => {
            return this.setState({ firstName: value })
    })
    }


    render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">

              <div>
                  <form onSubmit= {this.handleSubmit}>
                  <input type="text" onChange={this.handleChange}/>
                  <input type="submit"/>

              </form></div>
            <p>{this.state.firstName}</p>
            <p>{this.state.fName}</p>
        </p>


      </div>
    );
  }
}

export default App;

SimpleStorage.sol

pragma solidity 0.4.24;

contract SimpleStorage {
    string firstName;

    function set(string x) public {
        firstName = x;
    }

    function get() public view returns (string) {
        return firstName;
    }
}
2

I think that it's not correct way to import the smart contract into an dApp. The correct way should be as below code snippet

    let web3 = new Web3(new Web3.providers.HttpProvider(WEB3.HTTP))

    const SimpleStorage = web3.eth.contract(WEB3.ABI)
    const contract = SimpleStorage(WEB3.ADDRESS_CONTRACT)

So you need to declare three constant

  1. WEB3.HTTP is the http end-point of your node, E.x: http://localhost:8545
  2. WEB3.ABI smart contract abi
  3. WEB3.ADDRESS_CONTRACT smart contract address

Hope this help!

  • Note that WEB3.ABI in this example is the JSON you were trying to import in the original question, so I don't think it solves the problem. – Cliff Hall Oct 14 '18 at 22:33
2

The problem is that create-react-app has a prohibition on importing anything outside the src/ directory.

You can get around it by doing an eject but you probably don't want that because afterward you can't take advantage of updates to the create-react-app scripts. More on that here if you want to try: https://stackoverflow.com/a/44115058/203704

The approach I took was to reconfigure Truffle to compile the scripts to src/abi directory instead of the default build/contracts. To do that, (according to the docs) you only have to add a contracts_build_directory entry in your truffle.js file:

module.exports = {
    contracts_build_directory: "./src/abi",
    networks: {...}
};

However, I found this to have inconsistent behavior depending upon whether I ran compile before migrate or just let migrate -reset recompile and migrate, the upshot of which was that it would complain about not finding the src/abi folder.

I discovered that others had seen this same problem and the workaround was this:

const path = require('path');
module.exports = {
    contracts_build_directory: path.join(__dirname, "/src/abi"),
    networks: {...}
    }
};
  • this is working for me! – Vultur Jun 15 at 21:15

Your Answer

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

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