Server Bug Fix: How do you normalize client-side web3 libraries?

Original Source Link

In my web front-end, I need the ability to interact with the Ethereum blockchain.

  1. It’s possible a user has MetaMask installed.
  2. It’s possible a user is using the web without MetaMask installed.
  3. It’s possible a user is using an old dApp browser.
  4. It’s possible a user is using a modern dApp browser.

The following code takes care of all possibilities, and injects ethers.js as a last resort:

if (window.ethereum) { // Modern dapp browsers...
    window.web3 = new Web3(ethereum);
} else if (window.web3) { // Legacy dapp browsers...
    window.web3 = new Web3(web3.currentProvider);
} else { // Non-dapp browsers...
    window.web3 = ethers; // ethersjs provided library
}

It works! Great! I can make web3.eth.getBalance() calls and such.

Here’s where it gets hairy:

It appears that the exposed interface for dealing with Contracts is not uniform across libraries, both in terms of the constructor and order of parameters.

Have I approached this entirely wrong?

In your code:

window.web3 = new Web3(ethereum);
window.web3 = new Web3(web3.currentProvider);
window.web3 = ethers; // ethersjs provided library

Since web3.js and ethers.js are obviously two different modules (most likely implemented by two different groups), they have no reason to share the exact same API.

The fact that you can set your window.web3 to both is only because Javascript is a weakly-typed language, which allows you to do that at your own risk (of getting a runtime exception).

If you want to use both in a transparent manner, then you’ll need to implement a wrapper with a unified API.


Some details on the difference between strongly-typed languages and weakly-typed languages:

  • A strongly-typed language has stricter typing rules at compile time, which implies that errors and exceptions are more likely to happen during compilation.
  • A weakly-typed language has looser typing rules and may produce unpredictable results or may perform implicit type conversion at runtime.

I used to use the code you are using. When you assign your provider to window.web3 things will go wrong ( I don’t remember why ). But i changed my code and assigned my provider to a variable, also changed the way i check for the web3 existance and it worked without any problems:

Here is the Code:

let web3
if(typeof window !== 'undefined' && typeof window.ethereum !== 'undefined'){
  //getting Permission to access MetaMask
  window.ethereum.enable();
  web3 = new Web3(window.ethereum);

}else if (typeof window !== 'undefined' && typeof window.web3 !== 'undefined') {
  web3 = new Web3(window.web3.currentProvider);
  // In legacy MetaMasks, acccounts are always exposed

} else {
  // No Web3 detected
  const provider = new Web3.providers.HttpProvider(
    'https://rinkeby.infura.io/...'
  );
  web3 = new Web3(provider);

}

Make sure to change the last part and replace it with your own provider.

Tagged : / / /

Code Bug Fix: How do you format addresses for the deploy transaction of a contract?

Original Source Link

Why does my deploy transaction run into a runtime error when the constructor uses an address parameter but not contracts with 0 parameters or non-address datatypes?

I run into this error
runtime error

when I try to run the below code.
Even if I take out web3.utils.toHex() I still get the same error.
In the comments you can see that I’ve noted that other argument types work. What special needs to happen to addresses to format them correctly?

fs = require("fs")

const web3 = new (require("web3"))('HTTP://127.0.0.1:7545')
console.log("web3")

let accounts = [];
web3.eth.getAccounts().then(function(result){
    accounts = result
    console.log(accounts)
})

deployContract('false-resolve.sol', "DummyToken",[]).then(function(result){
    //THIS WORKS
    //deployContract('false-resolve.sol', "DummyToken",[])

    //THIS WORKS
    //deployContract('UintConstructor.sol', "UintConstructor", [ 1 ] ).then(function(r){
    //  console.log("UintConstructor._address", r._address) 
    //})

    deployContract('orocl.sol', "Oracle", [ web3.utils.toHex("0x786c35Ae953f94fc4Ffd31Edd0388d50fCF5Bb70") ] ).then(function(r){
        console.log("r._address", r._address)
    })
})
function deployContract(CONTRACT_FILE, contractName, args){
    const content = fs.readFileSync(CONTRACT_FILE).toString()
    const input = {
      language: 'Solidity',
      sources: {
        [CONTRACT_FILE]: {
          content: content
        }
      },
      settings: {
        outputSelection: {
          '*': {
            '*': ['*']
          }
        }
      }
    }

    var compiled = solc.compile(JSON.stringify(input))
    var output = JSON.parse(compiled)
    var abi = output.contracts[CONTRACT_FILE][contractName].abi
    var bytecode = output.contracts[CONTRACT_FILE][contractName].evm.bytecode.object.toString()
    var contract = new web3.eth.Contract(abi)

    var contractTx = contract.deploy({data: "0x"+bytecode, arguments: args});
    return contractTx.send({from: '0x786c35Ae953f94fc4Ffd31Edd0388d50fCF5Bb70', gas: 4700000})
}

Right now bytecode isn’t actually hex formatted data, you have it as a string with 0x in front of it.

You probably want to pass bytecode data directly:

...

var bytecode = output.contracts[CONTRACT_FILE[contractName].evm.bytecode;

...

var contractTx = contract.deploy({data: bytecode, arguments: args});

Referencing this stackoverflow question.

Tagged : /