0

I deployed a smart contract to ganache network using truffle from account1. The code of smart contract is as follows.

pragma solidity ^0.4.0;

import "./strings.sol";
import "./safemath.sol";
contract PublishService {

    using strings for *;
    using SafeMath for uint;
    struct ServiceListStruct {
        string cloudID;
        address gatewayID;
        string serviceProducerID;
        mapping (string => string) serviceProducerMetadata;
        string serviceConsumerMetaAttr;
        string accessControlModel;
    }

    ServiceListStruct[] public BCServiceList;

    uint BCServiceListIndex;

    function PublishService() {
        BCServiceListIndex = 0;
    }

    modifier onlyServiceProducerOwner(address _gatewayID) {
        require(msg.sender == _gatewayID);
        _;
    }

    ServiceListStruct sls;
    uint public maxParams = 0;


    function addEntry(string _cloudID, address _gatewayID, string _serviceProducerID, string _serviceProducerMetadata, string _serviceConsumerMetaAttr, string _accessControlModel) public onlyServiceProducerOwner(_gatewayID) returns (uint) {
        sls.cloudID = _cloudID;
        sls.gatewayID = _gatewayID;
        sls.serviceProducerID = _serviceProducerID;
        sls.serviceConsumerMetaAttr = _serviceConsumerMetaAttr;
        sls.accessControlModel = _accessControlModel;
        BCServiceList.push(sls);
        //
        string memory s1;
        string memory s2 = _serviceProducerMetadata;
        string memory s3;
        bytes memory s2bytes = bytes(_serviceProducerMetadata);
        uint paramCount = 0;
        while(s2bytes.length != 0) {
            (s1,s2) = splitString(s2,";");
            (s1,s3) = splitString(s1,":");
            BCServiceList[BCServiceListIndex].serviceProducerMetadata[s1] = s3;
            paramCount = paramCount.add(1);
            s2bytes = bytes(s2);
        }
        if(maxParams < paramCount) {
            maxParams = paramCount;
        }
        BCServiceListIndex = BCServiceListIndex.add(1);
        return 1;
    }

    function deleteEntry(string _cloudID, address _gatewayID, string _serviceProducerID) public onlyServiceProducerOwner(_gatewayID) returns (uint) {
        require(msg.sender == _gatewayID);
        int pos = -1;
        for(uint index = 0; index < BCServiceList.length; index++) {
            if(compareStringsbyBytes(_cloudID, BCServiceList[index].cloudID)) {
                if(_gatewayID == BCServiceList[index].gatewayID) {
                    if(compareStringsbyBytes(_serviceProducerID, BCServiceList[index].serviceProducerID)) {
                        pos = int(index);
                    }
                }
            }
        }
        if(pos > -1) {
             BCServiceList[index] = BCServiceList[BCServiceList.length -1];
             delete BCServiceList[BCServiceList.length - 1];
             BCServiceList.length--;
             return 1;
        }
        else
            return 0;
    }

    function compareStringsbyBytes(string s1, string s2) internal pure returns(bool) {
        bytes memory s1bytes = bytes(s1);
        bytes memory s2bytes = bytes(s2);
        if(s1bytes.length!=s2bytes.length) {
            return false;
        }
        else {
            for(uint i = 0; i < s1bytes.length; i++) {
                if(s1bytes[i] != s2bytes[i])
                return false;
            }
            return true;
        }
    }

    function splitString(string _s, string _seperator) internal returns(string, string) {
        var s_slice = _s.toSlice();
        var seperator_slice = _seperator.toSlice();
        string memory result = "";
        var result_slice = result.toSlice();
        result_slice = s_slice.split(seperator_slice);
        return (result_slice.toString(), s_slice.toString());
    }
}

Now i created an app.js file as below where I am trying to call a function of that smart contract using PublishService.addEntry(...).

var Web3 = require('web3');
var web3Provider = null;
var PublishService;
var contract = require('./PublishService_abi.js');

function init() {
  //initializing web3 to access blockchain
  initweb3();
}

function initweb3() {
  //To make sure not to overwrite the already set provider when in mist, check first if the web3 is available
  if (typeof web3 !== 'undefined') {
    web3 = new Web3(web3.currentProvider);
  } else {
    // create an instance of web3 using the HTTP provider
    web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:7545"));
  }
  web3.eth.defaultAccount = web3.eth.accounts[1];
  var PublishServiceContractAddress = "0x6c68d153b9709283e3900e944f1c6677273987c5";
  var PublishServiceContract = new web3.eth.Contract(contract,PublishServiceContractAddress ); 
  PublishService.addEntry("LC1", web3.eth.defaultAccount, "SP1", "location:inside;reading:degree", "scattr", "ngac");
}

init();

But this gives an error

TypeError: Cannot read property 'addEntry' of undefined

I followed many tutorials and they suggested the same, but I don't understand the reason for failure in my case.

Thanks!

0

You're calling a method on an object that does not exist.

Modify your code to

PublishServiceContract.addEntry("LC1",web3.eth.defaultAccount,"SP1","location:inside;reading:degree","scattr","ngac");
  • My mistake. but now I get this error TypeError: PublishServiceContract.addEntry is not a function – K Kolluru Apr 18 '18 at 15:09
0

Now I tried it this way, following the truffle pet-shop tutorial

var Web3 = require('web3');
var web3Provider = null;
var contract = require('./PublishService_abi.js');
var PublishServiceContract;

function init() {
  //initializing web3 to access blockchain
  initweb3();
}

function initweb3() {
  //To make sure not to overwrite the already set provider when in mist, check first if the web3 is available
  if (typeof web3 !== 'undefined') {
    web3 = new Web3(web3.currentProvider);
  } else {
    // create an instance of web3 using the HTTP provider
    web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:7545"));
  }
  web3.eth.defaultAccount = web3.eth.accounts[1];
  var PublishServiceContractAddress = "0x6c68d153b9709283e3900e944f1c6677273987c5";
 PublishServiceContract = new web3.eth.Contract(contract,PublishServiceContractAddress); 
  addServiceProducer("LC1","SP1","location:inside;reading:degree","scattr","ngac");
}

function addServiceProducer(s1,s2,s3,s4,s5) {
    var psinstance;
    PublishServiceContract.deployed().then(function(instance) {
        psInstance = instance;
        psinstance.addEntry(s1,web3.eth.defaultAccount,s2,s3,s4,s5);
    }).then(function(print) {
        console.log("sp details added successfully")
    }).catch(function(err) {
        console.log(err.message);
    });
}

init();

then I get the below error.

TypeError: PublishServiceContract.deployed is not a function

Any idea about the reason for this error?

Thanks in advance

0

If PublishService is your contract, you can't call functions just like that. You need to instanciate your contract, and it's an asynchronous function so you'll have to wait for callback or you contract variable will be undefined.

I assume you're trying to reach a contract by address. There are two steps for this.

  • init the contract, like in the truffle tutorial. (That shouldn't be done in initWeb3(), you should have an initContract() function.

  • Create an instance of the contract. In the tutorial they use App.contracts.myContract.deployed() but you can use App.contracts.myContract.at("0x6c68d153b9709283e3900e944f1c6677273987c5").

In the tutorial they use an init like this:

    initContract: function() {
        $.getJSON('Adoption.json', function(data) {
          // Get the necessary contract artifact file and instantiate it with truffle-contract
          var AdoptionArtifact = data;
          App.contracts.Adoption = TruffleContract(AdoptionArtifact);

          // Set the provider for our contract
          App.contracts.Adoption.setProvider(App.web3Provider);

          // Use our contract to retrieve and mark the adopted pets
          return App.markAdopted();
        });

        return App.bindEvents();
      },

You should do the same for your contract. Ask me if there's anything wrong.

Yours should look like this:

  initContract: function() {
    $.getJSON('PublishService.json', function(data) {
      var PublishServiceArtifact = data;
      App.contracts.PublishService = TruffleContract(PublishServiceArtifact);

      App.contracts.PublishService.setProvider(App.web3Provider);

      // you don't need to return anything specific so that should work
      return true
    });

    return App.bindEvents();
  },

And don't forget to call truffle compile and truffle migrate in your console.

  • Hi,the steps you showed below is basically to read the json file and set the provider, which I did in the following piece of code. var contract = require('./PublishService_abi.js'); and ` var PublishServiceContractAddress = "0x6c68d153b9709283e3900e944f1c6677273987c5"; PublishServiceContract = new web3.eth.Contract(contract,PublishServiceContractAddress); `, I tried to do async call as in the below answer, but I get error saying deployed is not a function. – K Kolluru Apr 19 '18 at 9:53
  • @KKolluru I don't get it, why don't you start from the pet shop tutorial and build from here? Replace the initContact function to feature your contract, and replace their function calls by your function. – Teleporting Goat Apr 19 '18 at 10:01
  • @KKolluru You also need to make your contract creation asynchronous. In the tutorial, they use App.contracts.Adoption.deployed(), but they can do that because the contract has be properly instanced vie the JSON abi. – Teleporting Goat Apr 19 '18 at 10:03

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.