trufflesuite/drizzle-legacy

When is drizzle.addContract done loading?

alexiskattan opened this issue · 12 comments

I have some code the is very similar to the example to add a contract.

var contractConfig = {
  contractName: "0x066408929e8d5Ed161e9cAA1876b60e1fBB5DB75",
  web3Contract: new web3.eth.Contract(/* ... */)
}
events = ['Mint']

// Or using the Drizzle context object
drizzle.addContract(contractConfig, events)

It works, sort of. The drizzle.addContract takes some time to load. So as a hack I do:

setTimeout(()=>{
 //my code
}, 2000)

which works.

Is there some even that is called or some other way to track when a dynamically loaded contract has been added?

Hi @alexiskattan The contract will eventually be added to Drizzle's redux store's list of contracts. You can inspect the specific contracts via store.contracts['contractName']. It is connected when store.contracts['contractName'].initialized is true

@cds-amal I would be interested in submitting a PR for a drizzle.addContractPromise (or a suggestion for a better name) that takes the same arguments as drizzle.addContract and returns a promise that is resolved once the contract is loaded. Let me know if that works for you.

Maybe even simpler without adding a new API is to just add an extra initCallback argument to addContract.

EDIT:

I am using redux-saga in my project and so I did the following to wait for contract initialization in one of my generator functions:

drizzle.addContract(...)

yield take(action => action.type == 'CONTRACT_INITIALIZED' 
                  && action.name == '[your-contract-name-here]')

I have the same problem, this fails in the constructor:

constructor(props, context) {
    super(props);
    var contractConfig = {
      contractName: this.props.address,
      web3Contract: new context.drizzle.web3.eth.Contract(
        abi,
        this.props.address,
        this.props.options
      )
    };
    context.drizzle.addContract(contractConfig, this.props.events);
    this.contracts = this.props.store.getState().contracts;
    this.state = {
      myMethodKey: this.contracts[
        this.props.address
      ].methods.myMethod.cacheCall()
    };
  }

Result:

TypeError: _this.contracts[_this.props.address] is undefined
  31 | context.drizzle.addContract(contractConfig, this.props.events);
  32 | this.contracts = this.props.store.getState().contracts;
  33 | this.state = {
> 34 |   myMethodKey: this.contracts[
  35 | ^    this.props.address
  36 |   ].methods.myMethod.cacheCall()
  37 | };

So, what is a good solution to solve this?

@mwaeckerlin Initialize the myMethodKey to undefined and you can do the OP's solution of doing a setTimeout and call setState to update myMethodKey when the contract is populated.

@mwaeckerlin Initialize the myMethodKey to undefined and you can do the OP's solution of doing a setTimeout and call setState to update myMethodKey when the contract is populated.

That's a dirty hack. I am looking for a proper solution without timeouts.

stale commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Is there no nice solution?

Looking for the exact same answer. My dapp dynamically adds contracts but I need to know when I can make a cacheCall to retrieve their data. Must we do the timer trick as described by @rahulmutt ?

@J-Mars If you don't use redux-saga, then yes, you must do the timer trick. Moreover, the redux-saga solution involves internal implementation details which may change in future versions of drizzle which is why I proposed that there be a stable API that provides this functionality in my earlier comment.

I was just waiting on a nod from the maintainers before working on it though.

@rahulmutt Thanks for staying on this and apologies for the delayed response.

I discussed your proposal with @adrianmcli and we like your stable API callback idea as it has minimal impact and isn't coupled to the drizzle internals.

Please, we would love to see a PR for this issue and thanks again.

stale commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale commented

This issue has been closed, but can be re-opened if further comments indicate that the problem persists. Feel free to tag maintainers if there is no reply to further comments.