Sending Transactions with Web3py
Tags: web3, python
Published: 2022-03-30 12:34:47

<p>
Web3 is a library for interacting with the Ethereum network. The library exists in both Python and JavaScript. Interacting with a blockchain either involves sending transactions, or interacting with smart contracts. In this article, you will learn how you can make transactions on Ethereum with Web3 on python.
</p>
<h1>Prerequisites</h1>
<p>
To fully understand this article, you need the following.
</p>
<ul>
<li>Any knowledge of the web3py library.
<li>Understanding of Python code.
</li>
</ul>
<h1>What is a Blockchain?</h1>
<p>
A blockchain is a data structure made of blocks that are connected together. The
arrangement of each block depends on when they were added. The block is
immutable are added to the end of other block.
</p>
<p>
In cryptocurrencies, blockchains are used to record transactions between two accounts. Different computers, called *nodes*, work together to mine blocks into the chain. Once a block
is mined, the node adds the mined block to the blockchain network. Mining is a computing intensive task, which involves calculating hashes, to securely attach new blocks.
</p>
<h1>Setting up a Local Network</h1>
<p>
To develop with the ethereum network you need to setup a local server, like <a href="https://geth.ethereum.org/">Geth</a>. A local server allows you simulate the blockchain network in your computer. Geth allows you to fork the public Ethereum network.
</p>


```bash
geth --syncmode light -[network] --http
```
<p>
Then replace <strong>[network]</strong> with the name of the network. The Ethereum network has different types. These types can be mainnet, rinkeby, ropsten, goerli, and so on. You can learn more about the other commands in the [command line section of the Geth documentation](https://geth.ethereum.org/docs/interface/command-line-options).
</p>

<p>
Before making any transaction in the Geth server, make sure that your Ethereum account is funded in the network you are using. Any transaction you make on the local server will not affect the public network.
</p>
<h1>Sending Transactions with Unlocked Accounts</h1>
<p>
Unlocked accounts do not require special any key to access them. You need access to an account to send transactions and do other operations with the account. Here is a simple example of a python script to send 5 ethers from `sender` to `receiver`:
</p>


```python
from web3 import Web3

# create an instance of `Web3` connected to the geth server
w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))      # `geth` creates the server at `http://127.0.0.8545`


sender = '0x12345......'          # sender's address
receiver = '0xabcdef......'        # receiver's address

# create and sign a transaction
tx_hash = w3.eth.send_transaction({        # `w3.eth.send_transaction` returns a transaction hash
    'to': receiver,
    'from': sender,
    'value': w3.toWei(5, 'ether'),    # convert the amount of ethers to Wei
})

# Wait for Geth to mine the transaction
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)

# Confirm that the Ethers were sent
print("sender's account: ", w3.eth.get_balance(sender))
print("receiver's account: ", w3.eth.get_balance(receiver))
```

> **Note**: One `Wei` equals 10^-18 `Eth`. You can reduce the amount of Ethers to send depending on your available amount. The account will not be deducted in the public network. 

<p>
Now, when you run the code, the sender's account should be reduced by 5 ethers, while the receiver's increase by 5 ethers. If you got an error message, you either don't have up to 5 ethers, or the account is locked.
</p>
<h1>Sending With Locked Accounts</h1>
<p>
A locked account requires a authentication methods to access them. To access a locked account you need its private key or its mnemonic. Here is an example of a python script to send 5 ethers from a locked `sender` account to `receiver`.
</p>


```python
from web3 import Web3

# create an instance of `Web3` connected to the geth server
w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))

# collect the sender and receiver address
sender_address = '0xabcd..............................'
receiver = '0x1234.....................'

# gain access to the sender's account  
sender = w3.eth.account.from_key('05d6c...............e')      # pass the sender's private key

# sign a transaction with the sender's account
signed_txn = sender.sign_transaction({
    'nonce': w3.eth.get_transaction_count(sender_address),
    'gas': 100000,
    'gasPrice': 100000,
    'to': receiver,                  # you don't need to specify the sender
    'value': w3.toWei(5, 'ether')
})

# extract raw transaction object from `signed_txn`
raw_transaction = signed_txn.rawTransaction

# send the transaction with the raw transaction
tx_hash = w3.eth.send_raw_transaction(raw_transaction)

# Wait for Geth to mine the transaction
receipt = w3.eth.wait_for_transaction_receipt(tx_hash)

# Confirm that the Ethers were sent
print("sender's account: ", w3.eth.get_balance(sender_address))
print("receiver's account: ", w3.eth.get_balance(receiver))
```

In the transaction object, the following might be confusing: 
* <strong>Nonce</strong>: is gotten from the `w3.eth.get_transaction_count()` function.
* <strong>Gas</strong>: shows the maximum amount of gas fee that the transaction can use.
* <strong>GasPrice</strong>:  is the integer used for each paid gas.


> **Note**: The `gasPrice` value is required if you are making legacy
transactions. Use `maxFeePerGas` and`maxPriorityFeePerGas` unless it is necessary to use `gasPrice`. Using those two instead of `gasPrice` is more efficient method.
> ```python
signed_txn = sender.sign_transaction({
    'nonce': w3.eth.get_transaction_count(sender_address),
    'gas': 100000,
    'maxFeePerGas': 3000000000,        # replacement for `gasPrice`
    'maxPriorityFeePerGas': 2000000000,       # replacement for `gasPrice`
    'to': receiver,
    'value': w3.toWei(5, 'ether')
})
```

<p>
Then when we run our code, we'll see that the sender's account has been reduced
by 5 ethers and the receiver's has increased by 5 ethers.
</p>
<h1>Conclusion</h1>
<p>
This article covers the process of sending Ethers from one account to another. I hope this article helped you in understanding how transactions are made over the network. To further your knowledge on the topic be sure to check out the following links:
* [Web3.py - Read the Docs](https://web3py.readthedocs.io/)
* [A guide to Ethereum blockchain development with Python](https://blog.logrocket.com/web3-py-tutorial-guide-ethereum-blockchain-development-with-python/)
* [Intro to Web3.py · Ethereum For Python Developers](https://www.dappuniversity.com/articles/web3-py-intro)