├── .env.example
├── requirements.txt
├── .gitignore
├── contracts
├── Greeter.sol
└── Greeter.json
├── README.md
├── templates
└── index.html
├── static
└── css
│ └── style.css
├── LICENSE
└── app.py
/.env.example:
--------------------------------------------------------------------------------
1 | PRIVATE_KEY=
2 | RPC_URL=
3 | CONTRACT_ADDRESS=
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | flask~=2.0.0
2 | web3==5.22.0
3 | simplejson~=3.17.2
4 | python-dotenv~=0.21.0
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build and Release Folders
2 | bin-debug/
3 | bin-release/
4 | [Oo]bj/
5 | [Bb]in/
6 |
7 | # Other files and folders
8 | .settings/
9 | __pycache__/
10 | # Executables
11 | *.swf
12 | *.air
13 | *.ipa
14 | *.apk
15 | .env
16 | *.env
--------------------------------------------------------------------------------
/contracts/Greeter.sol:
--------------------------------------------------------------------------------
1 | //SPDX-License-Identifier: MIT
2 | pragma solidity 0.8.16;
3 |
4 | contract Greeter {
5 | string greeting = "Hello Web3 Devs!";
6 |
7 | function setGreeting(string memory _greeting) public {
8 | greeting = _greeting;
9 | }
10 |
11 | function getGreeting() public view returns (string memory) {
12 | return greeting;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Python-Dapp
2 |
3 | web3.py based dapp
4 |
5 | #### Steps:
6 |
7 | 1. Deploy your contract on your preferred network(update `RPC_URL` accordingly) and get the contract address.
8 |
9 | 2. Create `.env` file in the root directory with below parameters:
10 |
11 | ```
12 | PRIVATE_KEY=
13 | RPC_URL=
14 | CONTRACT_ADDRESS=
15 | ```
16 |
17 | 3. Install dependencies and run app:
18 |
19 | ```bash
20 | pip install -r requirements.txt
21 |
22 | python app.py # open http://localhost:8000
23 |
24 | ```
25 |
--------------------------------------------------------------------------------
/contracts/Greeter.json:
--------------------------------------------------------------------------------
1 | {
2 | "abi": [
3 | {
4 | "inputs": [],
5 | "name": "getGreeting",
6 | "outputs": [
7 | {
8 | "internalType": "string",
9 | "name": "",
10 | "type": "string"
11 | }
12 | ],
13 | "stateMutability": "view",
14 | "type": "function"
15 | },
16 | {
17 | "inputs": [
18 | {
19 | "internalType": "string",
20 | "name": "_greeting",
21 | "type": "string"
22 | }
23 | ],
24 | "name": "setGreeting",
25 | "outputs": [],
26 | "stateMutability": "nonpayable",
27 | "type": "function"
28 | }
29 | ]
30 | }
--------------------------------------------------------------------------------
/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Greeter Dapp
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
{{greeting }}
14 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/static/css/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: #f6f5f7;
3 | display: flex;
4 | justify-content: center;
5 | align-items: center;
6 | flex-direction: column;
7 | font-family: 'Montserrat', sans-serif;
8 | height: 100vh;
9 | margin: -20px 0 50px;
10 | }
11 | input {
12 | background-color: #eee;
13 | border: none;
14 | padding: 12px 15px;
15 | margin: 8px 0;
16 | width: 100%;
17 | }
18 | .button{
19 | border-radius: 20px;
20 | border: 1px solid #FF4B2B;
21 | background-color: #FF4E2B;
22 | color: #FFFFFF;
23 | font-size: 12px;
24 | font-weight: bold;
25 | padding: 12px 45px;
26 | letter-spacing: 1px;
27 | text-transform: uppercase;
28 |
29 | transition: transform 80ms ease-in;
30 | }
31 | .button:hover{
32 | opacity: 0.4;
33 | }
34 | .main {
35 | background: #FF416C;
36 | background: -webkit-linear-gradient(to right, #FF4B2B, #FF416C);
37 | background: linear-gradient(to right, #FF4B2B, #FF416C);
38 | background-repeat: no-repeat;
39 | background-position: 0 0;
40 | color: #FFFFFF;
41 | width: 30%;
42 | height: 45%;
43 | transform: translateX(0);
44 | transition: transform 0.6s ease-in-out;
45 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Salman Dabbakuti
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 | from dotenv import load_dotenv
4 | from web3 import Web3, Account, HTTPProvider
5 | from flask import Flask, render_template, request
6 |
7 | # load environment variables from .env file
8 | load_dotenv('.env')
9 |
10 | # web3.py instance
11 | w3 = Web3(HTTPProvider(os.environ.get('RPC_URL')))
12 | print('Web3 Connected:',w3.isConnected())
13 |
14 | # account setup
15 | private_key= os.environ.get('PRIVATE_KEY') #private key of the account
16 | public_key = Account.from_key(private_key)
17 | account_address = public_key.address
18 |
19 | # Contract instance
20 | contract_artifacts_file = json.load(open('./contracts/Greeter.json'))
21 | abi = contract_artifacts_file['abi']
22 | contract_address = os.environ.get('CONTRACT_ADDRESS')
23 | contract_instance = w3.eth.contract(abi=abi, address=contract_address)
24 |
25 | app = Flask(__name__)
26 |
27 | @app.route("/")
28 | def index():
29 | greeting = contract_instance.functions.getGreeting().call()
30 | return render_template("index.html", greeting=greeting)
31 |
32 | @app.route("/setGreeting" , methods=['POST'])
33 | def set_greeting():
34 | greeting_input = request.form.get("greeting")
35 | tx = contract_instance.functions.setGreeting(greeting_input).buildTransaction({'nonce': w3.eth.get_transaction_count(account_address)})
36 | signed_tx = w3.eth.account.sign_transaction(tx, private_key)
37 | tx_hash= w3.eth.send_raw_transaction(signed_tx.rawTransaction)
38 | print('Transaction submitted:', tx_hash.hex())
39 | w3.eth.wait_for_transaction_receipt(tx_hash)
40 | greeting = contract_instance.functions.getGreeting().call()
41 | return render_template("index.html", greeting=greeting)
42 |
43 | if __name__ == '__main__':
44 | app.run(port=8000, host='localhost')
45 |
--------------------------------------------------------------------------------