web3.py
Web3.py and Web3.js are a set of libraries that facilitate the interaction of developers with Conflux nodes via the HTTP, IPC, or WebSocket communication protocols, using the Python and JavaScript programming languages respectively. This guide will provide you with the expertise to leverage the Web3.py library for transmitting transactions and deploying smart contracts.
Initiate a Project
To start, first create a directory where all the relevant files generated throughout this guide can be stored. Execute this task with the following command:
mkdir web3-examples && cd web3-examples
For the successful implementation of the upcoming sections, you'll need to install the Web3 library and the Solidity compiler. To obtain both packages, execute the following command:
pip3 install web3 py-solc-x
Setup the HTTP connection
Prepare your Web3 HTTP connection to align with any evm-powered network. To synchronize your project, you must secure an endpoint and API key of your own. Here's how you can get started with each network, step by step.
# Import Web3 library into your project:
from web3 import Web3
# Configure the HTTP connection to your RPC endpoint:
web3 = Web3(Web3.HTTPProvider('RPC-API-ENDPOINT-HERE'))
You can find Conflux eSpace Network Endpoints here.
Send a Transaction and check the balances
In this section, you will learn how to create two scripts in order to send a transaction between two accounts. The first script will be used to check the balances of the accounts before and after the transaction is sent. The second script will actually send the transaction.
Check the balances
To begin with the first script, you need to create a file called "balances.py" using the command "vim balances.py". In this file, you will set up the Web3 provider, define the variables "sender_address" and "recipient_address", and retrieve the balances of these accounts using the "web3.eth.get_balance" function. You will then format the results using the "web3.fromWei" function and print the balances in your terminal using the "print" function. To run the balances script, enter the command "python3 balances.py" in your terminal. The balances for the sender and recipient addresses will be displayed in your terminal in CFX.
# Set up the Web3 provider
from web3 import Web3
web3 = Web3(Web3.HTTPProvider('RPC-API-ENDPOINT-HERE'))
# Define address variables
sender_address = "SENDER-ADDRESS-HERE"
recipient_address = "RECIPIENT-ADDRESS-HERE"
# Retrieve balance data
balance_sender = web3.fromWei(web3.eth.get_balance(sender_address), "ether")
balance_recipient = web3.fromWei(web3.eth.get_balance(recipient_address), "ether")
# Display balances in the terminal
print(f"The balance of { sender_address } is: { balance_sender } CFX")
print(f"The balance of { recipient_address } is: { balance_recipient } CFX")
Send a transaction
To begin with the second script, you need to create a "transaction.py" file using the command "vim transaction.py". Within this file, you will import "rpc_gas_price_strategy" to obtain the gas price for the transaction. Then you will establish the Web3 provider, define the "sender" and "receiver" variables (including the private key for the "sender" account), establish the gas price strategy using the "web3.eth.set_gas_price_strategy" function, create and sign the transaction using the "web3.eth.account.sign_transaction" function, and send the transaction using the "web3.eth.send_raw_transaction" function. You will then wait for the transaction receipt using the "web3.eth.wait_for_transaction_receipt" function and print the transaction hash in your terminal.
To execute the transaction script, run the command "python3 transaction.py" in your terminal. If the transaction is successful, the transaction hash will be displayed in your terminal. You can also use the balances script to verify that the balances for the origin and receiving accounts have changed.
# Import the gas strategy
from web3.gas_strategies.rpc import rpc_gas_price_strategy
# Put the Web3 provider snippet here
from web3 import Web3
web3 = Web3(Web3.HTTPProvider('RPC-API-ENDPOINT-HERE'))
# Define variables for addresses
sender = {
"private_key": "YOUR-PRIVATE-KEY-HERE",
"address": "PUBLIC-ADDRESS-OF-PK-HERE",
}
receiver = "ADDRESS-TO-HERE"
print(f'Attempting to send transaction from { sender["address"] } to { receiver}')
# Establish the gas price strategy
web3.eth.set_gas_price_strategy(rpc_gas_price_strategy)
# Sign transaction with private key
tx_create = web3.eth.account.sign_transaction(
{
"nonce": web3.eth.get_transaction_count(sender["address"]),
"gasPrice": web3.eth.generate_gas_price(),
"gas": 21000,
"to": receiver,
"value": web3.toWei("1", "ether"),
},
sender["private_key"],
)
# Send transaction and wait for receipt
tx_hash = web3.eth.send_raw_transaction(tx_create.rawTransaction)
tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
print(f"Transaction successful with hash: { tx_receipt.transactionHash.hex() }")
Deploy a Contract
Initialize a Smart Contract
Within the following sections, you will be initializing and executing a straightforward incremental contract named Incrementer.sol. You may commence the process by generating a file for the contract:
vim Incrementer.sol
Once you have created the file, the subsequent step is to input the Solidity code into the file:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Incrementer {
uint256 public numericVal;
constructor(uint256 _startVal) {
numericVal = _startVal;
}
function increaseVal(uint256 _inputVal) public {
numericVal = numericVal + _inputVal;
}
function resetVal() public {
numericVal = 0;
}
}
When the contract is deployed, the constructor function executes and assigns the starting value to the numericVal variable that is stored on the blockchain (the default is 0). By invoking the increaseVal function, the supplied _inputVal is added to the existing value. Note that executing this function requires sending a transaction, which alters the stored data. Lastly, the resetVal function reassigns the stored value to zero.
Compile the Contract
This section will guide you through the process of building a script that leverages the Solidity compiler to produce the ABI and bytecode for the Incrementer.sol contract. Start by generating a compile.py and fill it as bellow:
# Import the compiler library
import solcx
# If you have already installed the Solidity compiler, comment next line
solcx.install_solc()
# Compile contract
comp_output = solcx.compile_files('Incrementer.sol')
# Export contract data
abi = comp_output['Incrementer.sol:Incrementer']['abi']
bytecode = comp_output['Incrementer.sol:Incrementer']['bin']
部署
To deploy the Incrementer.sol contract, you need to first compile the contract using a script and then create a deployment script file called deploy.py. The deployment script file must complete several steps, including importing the ABI and bytecode, setting up the Web3 provider, defining the account_from with the private_key, creating a contract instance, building a constructor transaction, signing the transaction, sending it using web3.eth.send_raw_transaction function, and waiting for the transaction receipt by using web3.eth.wait_for_transaction_receipt function. It's essential to note that the private key should never be stored in a Python file. With these steps completed, you can successfully deploy the Incrementer.sol contract.
from compile import abi, bytecode
from web3 import Web3
web3 = Web3(Web3.HTTPProvider('RPC-API-ENDPOINT-HERE'))
account_from = {
'private_key': 'YOUR-PRIVATE-KEY-HERE',
'address': 'PUBLIC-ADDRESS-OF-PK-HERE',
}
print(f'Attempting to deploy from account: { account_from["address"] }')
Incrementer = web3.eth.contract(abi=abi, bytecode=bytecode)
construct_txn = Incrementer.constructor(5).buildTransaction(
{
'from': account_from['address'],
'nonce': web3.eth.get_transaction_count(account_from['address']),
}
)
tx_create = web3.eth.account.sign_transaction(construct_txn, account_from['private_key'])
tx_hash = web3.eth.send_raw_transaction(tx_create.rawTransaction)
tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash)
print(f'Contract deployed at address: { tx_receipt.contractAddress }')