7

the orgin question is below:

How to connect to Ropston and deploy contract use web3.py?
I have deploy a contract to Ropston use remix and MetaMask.
I want know how to deploy a contract to Ropston via infura using web3.py without geth or parity.
I read the Documention and find there is no how-to chapter.
A small demo code will be very helpful.

And I just search and try And find this code can work. But, buildTransaction()function can't add args to and nonce (will get errorValueError: Cannot set nonce in transaction) And if I just not add to nonce to transaction in signTransaction() function I will get errorTypeError: Not all fields initialized

There must be something wrong. I guess I should use another function rather than buildTransaction() But I can't find it in document.

So, what function I should use? And what's pythonic way to deploy contract to https://ropsten.infura.io/ ?

from eth_account import Account
from web3 import Web3, HTTPProvider
from solc import compile_source

privateKey = "xxxxxx"
contract_source_code = '''
pragma solidity ^0.4.0;

contract Greeter {
    string public greeting;

    function Greeter() {
        greeting = 'Hello';
    }

    function setGreeting(string _greeting) public {
        greeting = _greeting;
    }

    function greet() constant returns (string) {
        return greeting;
    }
}
'''

compiled_sol = compile_source(contract_source_code)
contract_interface = compiled_sol['<stdin>:Greeter']
w3 = Web3(HTTPProvider("https://ropsten.infura.io/"))
w3.eth.enable_unaudited_features()
account = Account()
acct = account.privateKeyToAccount(privateKey)
contract_ = w3.eth.contract(abi=contract_interface['abi'], bytecode=contract_interface['bin'])
contract_data = contract_.constructor().buildTransaction({'from': acct.address,
                                                          'gas': 1728712,
                                                          'gasPrice': w3.toWei('21', 'gwei')})
contract_data["to"] = ""  # <----
contract_data["nonce"] = w3.eth.getTransactionCount(acct.address)   #<------
signed = w3.eth.account.signTransaction(contract_data, privateKey)
w3.eth.sendRawTransaction(signed.rawTransaction)
6

As of v4.2.1, deploying a contract with a local key is a lot more straightforward.

From the question's example code, here is a new approach:

w3 = Web3(HTTPProvider("https://ropsten.infura.io/v3/YOUR_PROJECT_ID"))

contract_ = w3.eth.contract(
    abi=contract_interface['abi'],
    bytecode=contract_interface['bin'])

acct = w3.eth.account.privateKeyToAccount(privateKey)

construct_txn = contract_.constructor().buildTransaction({
    'from': acct.address,
    'nonce': w3.eth.getTransactionCount(acct.address),
    'gas': 1728712,
    'gasPrice': w3.toWei('21', 'gwei')})

signed = acct.signTransaction(construct_txn)

w3.eth.sendRawTransaction(signed.rawTransaction)
3

Using web3.py version 4.2.1, you can do something like this to deploy your contract through infura nodes:

from web3 import Web3

class DeployContract:
    def __init__(self, abi, bin, public_key, private_key):
        provider = 'https://ropsten.infura.io/YOUR_INFURA_KEY'
        self.w3 = Web3(Web3.HTTPProvider(provider))
        self.abi = abi # Your contract ABI code
        self.bin = bin # Your contract ByteCode 
        self.priv = private_key
        self.pub = public_key

    def deploy(self):
        instance = self.w3.eth.contract(abi=self.abi, bytecode=self.bin)
        # hacky .. but it works :D
        tx_data = instance.constructor().__dict__.get('data_in_transaction')
        transaction = {
            'from': self.pub, # Only 'from' address, don't insert 'to' address
            'value': 0, # Add how many ethers you'll transfer during the deploy
            'gas': 2000000, # Trying to make it dynamic ..
            'gasPrice': self.w3.eth.gasPrice, # Get Gas Price
            'nonce': self.w3.eth.getTransactionCount(self.pub), # Get Nonce
            'data': tx_data # Here is the data sent through the network
        }
        # Sign the transaction using your private key
        signed = self.w3.eth.account.signTransaction(transaction, self.priv)
        #print(signed.rawTransaction)
        tx_hash = self.w3.eth.sendRawTransaction(signed.rawTransaction)
        print(tx_hash.hex())
0

You need to have access to a node in all cases. Citing web3.py Read the docs:

You can connect to your Ethereum node (for example: geth or parity) using one of the available Providers, typically IPC or HTTP.

If your node is running locally, IPC will be faster and safer to expose. If sharing the node across machines on a network, use HTTP instead. Blockquote

So you need to connect to apublic node, for example (taken from here):

w3 = Web3.providers.HttpProvider('https://api.myetherapi.com/eth')

Then you can do your magic with w3!. However, the main issue here is how to manage your keys myetherapi does not allow methods that involve account.

Note: I have not used myetherapi.com!

I hope this help.

  • you are right,I have run some code using geth.But in this project,I have to use infura. I want to know how to do it. – Abirdcfly Apr 4 '18 at 1:25
  • I would recommend using Alchemy (alchemyapi.io), instead of Infura. We found that Infura was unreliable and had significant downtime. – hhppj Mar 7 at 22:04

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.