How to interact with Blockchain via Web3.py
Blockchain's role grows every day. In today's world Blockchain is a part of many products. And usually, we need to interact with blockchain from our web platform.
In this writing, we will not get deep into blockchain details(how to write contracts, how to deploy them, and so on). We consider that all pure blockchain job is done. So we have a smart contract and its address.
Infura is a kind of node storage (cluster). A set of tools that provides its services for integrating your application with the Ethereum network.
With its help, we successfully remove one of the most difficult barriers to blockchain adoption. Running a node requires a decent level of technical knowledge, patience, processing power, and memory. Using an app like Infura makes it unnecessary for us.
MetaMask allows users to store and manage account keys, broadcast transactions, send and receive Ethereum-based cryptocurrencies and tokens, and securely connect to decentralized applications through a compatible web browser or the mobile app’s built-in browser.
Connect to a blockchain
We will use two classes — Config and BlockchainInteraction. One for setting config params and one for interaction.
First of all, we need to create a project in Infura. Remember, that Infura allows one project for one contract. If you do some changes in your contract and re-deploy it, the contract id is changing, so you need to create another project.
Our Config class should contain project id
class Config:
BLOCKCHAIN_URL = 'https://ropsten.infura.io/v3'
def __init__(self, project_id):
self.project_id = project_idclass BlockchainInteraction:
def __init__(self, config):
self.is_connected = None
self.config = config def __is_connected(self, config):
w3 = Web3(Web3.HTTPProvider(‘{}/{}’.format( config.BLOCKCHAIN_URL, config.project_id)))
if w3.isConnected():
self.is_connected = True
self.w3 = w3
return True
return False
def setup(self):
self.__is_conencted()
in run.py
PROJECT_ID = 'my_project_id'if __name__ == "__main__":
cfg = Config(PROJECT_ID)
bi = BlockchainInteraction(cfg)
bi.setup()
print("Is connected — ", bi.is_connected)
Generate account
After connecting we should generate an account. First of all generate private_key(keep private key somewhere safe, we need it every time we do transactions). Feel free to choose how to generate your private key.
class BlockchainInteraction:...
def __generate_private_key(self, length: int) -> str: alphabet62 = string.digits + string.ascii_letters self.config.private_key = '0x' + ''.join(random.choice(alphabet62) for _ in range(length)) def __generate_account(self) -> None:
acnt = self.config.w3.eth.account.privateKeyToAccount(self.config.private_key)
self.config.account_address = acnt.address
ABI — application binary interface
After connecting to Blockchain, we need to set up a w3 object for our contract. For that, we need an ABI of the smart contract.
ABI is an interface between two binary program modules. In our case it is the interface for our smart contract.
Add account_address, contract_address, and ABI to our config
class Config:
BLOCKCHAIN_URL = ‘https://ropsten.infura.io/v3'
def __init__(self, project_id, abi, cont_addr):
self.project_id = project_id
self.account_address = None
self.abi = ast.literal_eval(str(abi))
self.contract_address = cont_addr
and __setup_contract() function to BlockchainInteraction class
class BlockchainInteraction: ...
def __setup_contract(self):
self.w3.eth.defaultAccount = self.config.account_address
self.contract = self.w3.eth.contract( address=self.config.contract_address, abi = self.config.abi) def setup(self):
self.__is_connected()
self.__setup_contract()
All functions
when all is setup, we can now interact with blockchain. For example, see all functions our smart contract provides
add all_functions() to BlockchainInteraction
class BlockchainInteraction:...
def all_functions(self):
return self.contract.all_functions()
Write to blockchain
For writing in Blockchain we need to call a function from our smart contract, which writes data in the blockchain. We need following
create transaction
transaction = self.contract.functions.insertDigest(data).buildTransaction({ 'gas': est_gas + 10000,
'gasPrice': Web3.toWei('1', 'gwei'),
'from': self.config.account_address,
'nonce': 'YOUR_NONCE'
})
sign transaction
signed_txn = self.w3.eth.account.signTransaction(
transaction,
private_key=self.config.private_key
)
send transaction
output = self.w3.eth.sendRawTransaction(signed_txn.rawTransaction)
wait for the transaction to complete
txn_receipt = self.w3.eth.waitForTransactionReceipt(output)
add function write_to_blockchain() to BlockchainInteraction.
Get from blockchain
And finally, get/read data from the blockchain.
class BlockchainInteraction:...
def get_from_blockchain(self, data):
return self.contract.functions.getDigest(data).call()
You can find the full code here.
Thanks for reading !!!
If you find this article interesting and helpful, please share and 👏