Web3.py: From Ganache to Infura
Tags: testnet, web3py, ethereum, smartcontracts
Published: 2021-04-12 21:41:21

---
title: Web3.py: From Ganache to Infura
published: true
date: 2021-04-08 10:36:27 UTC
tags: testnet,web3py,ethereum,smartcontracts
canonical_url: https://medium.com/coinmonks/web3-py-from-ganache-to-infura-3c16aadb0a0
---

![](https://cdn-images-1.medium.com/max/1024/0*EUjcggDt2unms_p6)<figcaption>Photo by <a href="https://unsplash.com/@hishahadat?utm_source=medium&amp;utm_medium=referral">Shahadat Rahman</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption>

#### You can find the full code for this tutorial [here](https://github.com/theodoros701/Web3py-From-Ganache-to-Infura)

I have been experimenting with smart contracts for some time but until recently I was only using Ganache (a personal development blockchain) to test things. Ganache is great for development and testing purposes, but any serious project eventually needs to be moved to a testnet for further testing. In this article, I will go through the changes I needed to make to my code in order to deploy and interact with my smart contracts on the Ropsten testnet using a hosted node like Infura.

You don’t necessarily need to use Infura to deploy a smart contract on the testnet. Some people chose to run their own nodes, and I imagine the transition from Ganache to a local node would be really smooth with the only code change being the web3 provider. Unfortunately, running a local node requires a lot of storage, computation and bandwidth and therefore not everyone is willing to do it. So for most, the only option is to use a hosted node like Infura. Using Infura requires some change to our code however.

In order to illustrate these changes, let’s start with a really simple smart contract that just stores a number and allows anyone to change it. The contract will also emit an event informing listeners that the number has changed.

```
contract darkPool {
  uint public num;

  event chage(uint number);

  function set(uint _num) external {
    num = _num;
    emit change(num);
  }
}
```

Next, we will see the changes we need to make to deploy our contract, send transactions and listen to events when using a hosted node.

The first change in our code should be the web3 provider. Using Ganache we usually have something like this:

```
w3 = Web3(HTTPProvider("[http://127.0.0.1:8545](http://127.0.0.1:8545)"))
```

Using Infura is not much different, we just need to provide the Infura endpoint for our project, which can be found under project settings in Infura, and should look something like this for the Ropsten testnet:

```
w3 = Web3(HTTPProvider("https://ropsten.infura.io/v3/<PROJECT ID>"
```

The next change we need to make, is in the way we deploy our contract. Using Ganache we just call the constructor:

```
tx_hash = contract.constructor().transact()
```

Using a hosted node, we can't just do that since the node doesn’t manage our keys for us so we need to do a bit more work. We first need to build the transaction providing some parameters like the ones below, then sign it using our private key and finally send it to the node:

```
# build transaction
build_tx = contract.constructor().buildTransaction({
    'from': ...,
    'nonce': ...,
    'gas': ...,
    'gasPrice': ...
})
private_key = ...
# sign transaction
sign_tx = w3.eth.account.signTransaction(build_tx, private_key)
# send the transaction
tx_hash = w3.eth.sendRawTransaction(sign_tx.rawTransaction)
```

Executing functions locally (i.e. calls) remains the same, so getting the current number stored in our contract is the same for both Ganache and Infura:

```
num = contract.functions.num().call()
```

Executing functions by sending transactions on the other hand is again different (as we saw with the contract constructor). Using Ganache we simply write:

```
tx_hash = contract.functions.set(num).transact()
```

To run the same thing on the testnet using Infura, we can do the following:

```
num = ...
# build transaction
build_tx = contract.functions.set(num).buildTransaction({
    'from': ...,
    'nonce': ...,
    'gas': ...,
    'gasPrice': ...
})
# sign transaction
sign_tx = w3.eth.account.signTransaction(build_tx, private_key)
# send the transaction
tx_hash = w3.eth.sendRawTransaction(sign_tx.rawTransaction)
```

Finally, when using a local node, we can create event filters and later get all published events. Using Ganache we can do the following:

```
filter = contract.events.change.createFilter(fromBlock="latest")

...

changes = filter.get_new_entries()
```

Our connection to Infura on the other hand is stateless so we can’t do the same. An alternative that works is:

```
start = ... # the block from which to start getting logs
changes = contract.events.change.getLogs(fromBlock=start)
```

I spent some time trying to figure how to make my code work the first time I tried to test a smart contract on the testnet. Hopefully, this article (and the accompanying code) will save you the trouble!

* * *