DEV Community

Mrhili Mohamed Amine
Mrhili Mohamed Amine

Posted on

Ho i managed to put my first etherium smart-contract on a testnet using python

Seting up the Environment

First i downloaded python in my windows machine using the link below

https://www.python.org/

The most important thing is to get the build tools necessary for the web3 library in my case i needed V++ 2019 build tools

Use the link bellow and scroll down to Tools for Visual Studio to get the online installer and install the needed version

https://visualstudio.microsoft.com/downloads/?q=build+tools

Get a metamask wallet for the test only and create an account and register down

the passphrase, Account adress, The private keys

in the metamask network section reveal the testnet because we will use rinkbey test for this purpose

Get some etherium for the test using youre metamasc wallet here:

https://www.youtube.com/watch?v=qsvwg-cC928

https://faucets.chain.link/

Create an account in https://infura.io/

Create a project and name it however you like Just dont forget to turn the rinkby network after the creation process.
and write down the Project_id and the Project secret and the first endpoint

If you dont like Infura you can use : https://t.co/Ky3JWP8GPZ

Install Visualstudio code in the link bellow

https://code.visualstudio.com/

Install some usefull extensions for solidity and python

Open a new project and start creatingthose files:

  • deploy.py
  • SimpleStorage.sol
  • .env

create a virtual env and we will name it 'venv' with this command :

py -m venv venv
Enter fullscreen mode Exit fullscreen mode

start using it now with this command each time you you open the powershell with :

venv\Scripts\activate
Enter fullscreen mode Exit fullscreen mode

start installing the necessary libraries

pip install web3
pip install python-dotenv
pip install py-solc-x
Enter fullscreen mode Exit fullscreen mode

SimpleStorage.sol

The code for the SimpleStorage.sol is :



 // SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.9.0;

contract SimpleStorage {

    uint256 favoriteNumber;

    // This is a comment!
    struct People {
        uint256 favoriteNumber;
        string name;
    }

    People[] public people;
    mapping(string => uint256) public nameToFavoriteNumber;

    function store(uint256 _favoriteNumber) public {
        favoriteNumber = _favoriteNumber;
    }

    function retrieve() public view returns (uint256){
        return favoriteNumber;
    }

    function addPerson(string memory _name, uint256 _favoriteNumber) public {
        people.push(People(_favoriteNumber, _name));
        nameToFavoriteNumber[_name] = _favoriteNumber;
    }
}
Enter fullscreen mode Exit fullscreen mode

In the code above we just have a favoriteNumber variable that we can check with retrieve function and modify with the store functionand we can associate someone name with a favorite number with addPerson function

Deploy.py

the code of the deploy.pyshould be the same as:

#Necessary
import json
import os
from pathlib import Path

#Security
from dotenv import load_dotenv

#Web3
from solcx import compile_standard, set_solc_version
from web3 import Web3






#Get hidden variables

load_dotenv(Path('.env'))

ENV_TYPE = os.getenv('ENV_TYPE')
#GANACHE
PRIVATE_KEY = os.getenv('PRIVAT_KEY')
ACCOUNT = os.getenv('ACCOUNT')

#INFURA
INFURA_ID = os.getenv('INFURA_ID')
INFURA_SEC = os.getenv('INFURA_SEC')
ENDPOINT_RINKBY = os.getenv('ENDPOINT_RINKBY')
#METAMASK
META_ADRESS = os.getenv('META_ADRESS')
META_PRV = os.getenv('META_PRV')


#SETUP THE CONTRACT

with open(Path('SimpleStorage.sol'), "r") as f:


    ss_file = f.read()



_solc_version = "0.6.0"

compiled_ss = compile_standard({
    "language":"Solidity","sources": {"SimpleStorage.sol": {"content": ss_file}},
    "settings":{
        "outputSelection":{
            "*":{
                "*":["abi", "metadata", "evm.bytecode","evm.sourceMap"]
            }
        }
    }

}, solc_version ="0.6.0")


with open(Path('compiled.json'), 'w' ) as f:

    json.dump(compiled_ss, f)

#get bytecode
bytecode= compiled_ss["contracts"]["SimpleStorage.sol"]["SimpleStorage"]["evm"]["bytecode"]["object"]
#get ABI
abi= compiled_ss["contracts"]["SimpleStorage.sol"]["SimpleStorage"]["abi"]


#SETUP PRIVATE KEYS

if ENV_TYPE == "INFURA":

    w3 = Web3(Web3.HTTPProvider(ENDPOINT_RINKBY))
    chain_id = 4

    my_address = META_ADRESS
    private_key = META_PRV

else:

    w3 = Web3(Web3.HTTPProvider("HTTP://127.0.0.1:8545"))
    chain_id = 1337

    my_address = ACCOUNT
    private_key = PRIVATE_KEY




ss = w3.eth.contract(abi=abi, bytecode=bytecode)


if  w3.isConnected():
    # print(ss)

    #get latest transaction to build the nounce
    nonce=w3.eth.getTransactionCount(my_address)
    #build transact
    #sign
    #send transact
    deploy_transaction = ss.constructor().buildTransaction({"gasPrice": w3.eth.gas_price,"chainId": chain_id, "from": my_address, "nonce": nonce})

    nonce = nonce+1    
    #Sign transaction
    signed_txn = w3.eth.account.sign_transaction(deploy_transaction, private_key=private_key)


    #send to blockchain

    print("deploying contract ...")

    txn_hash =  w3.eth.send_raw_transaction( signed_txn.rawTransaction )

    tx_receipt = w3.eth.wait_for_transaction_receipt(txn_hash)

    print("tx_receipt =>", tx_receipt)

    ##Contract adress and ABI

    contract_adress = tx_receipt.contractAddress

    #for interaction
    #transact or call

    ss_contract =  w3.eth.contract(address=contract_adress, abi=abi)


    store_transaction = ss_contract.functions.store(7).buildTransaction({"gasPrice": w3.eth.gas_price,"chainId": chain_id, "from": my_address, "nonce": nonce})


    signed_store_txn = w3.eth.account.sign_transaction(store_transaction, private_key=private_key)


    #send to blockchain

    print("interacting with store function ...")

    txn_store_hash =  w3.eth.send_raw_transaction( signed_store_txn.rawTransaction )

    tx_store_receipt = w3.eth.wait_for_transaction_receipt(txn_store_hash)

    print("tx_store_receipt =>", tx_store_receipt)

    print("---")

    print("call retreive =>", ss_contract.functions.retrieve().call())







else:

    print("Error not conected")

    quit()
Enter fullscreen mode Exit fullscreen mode

In the code above we are creating the smart contractin the blockchain and interacting with it by storing the number 7 in favoriteNumber and the checkingit

.env/Private keys

Now we should fill the necessary keys, you can escape the first two variables because it only needed in a local interaction with Ganache

.env file

ACCOUNT="0xRandom3216547986549687"
PRIVAT_KEY="0xRandom3216547986549687"


INFURA_ID="654random65465"
INFURA_SEC="654random65465"

META_ADRESS="0x654random65465"
META_PRV="654random65465"

ENDPOINT_RINKBY="654random65465"

ENV_TYPE="INFURA"
Enter fullscreen mode Exit fullscreen mode

Deploying/Interaction

You just need a final step is running :

py deploy.py

I hope everything fine

if so check you contract here :

https://rinkeby.etherscan.io/address/write_the_adress_of_the_contract

you can get the contract adress with the info given by youre python output

'contractAddress': '0x21321random321321'

for the needygreedy tutorialplease follow it here:

Top comments (0)