Skip to content

Instantly share code, notes, and snippets.

@danilobellini
Created July 24, 2018 17:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danilobellini/4fc5109708a1ce7808efcbf836f8fe81 to your computer and use it in GitHub Desktop.
Save danilobellini/4fc5109708a1ce7808efcbf836f8fe81 to your computer and use it in GitHub Desktop.
Sanic (Python) web server for storing a single information note in the Ethereum blockchain
"""
Application to store a single message note in the Ethereum blockchain.
In order to run this web server, the ethereum node daemon
(e.g. the Geth HTTP RPC on 8545) should be running in the same host.
Input parameters should be on the following environment variables:
export ETH_CONTRACT_ADDRESS=0xAAAA... # Enforced
export ETH_NODE_URL='http://localhost:8545' # Optional
Command to run the application (it requires Python 3.6+):
python3 -m sanic --host 0.0.0.0 --port 1337 ethereum_note.app
To install a virtualenv with its requirements (bash):
python3 -m venv somewhere/with/your/virtualenv
source somewhere/with/your/virtualenv/bin/activate
python3 -m pip install sanic web3
By Danilo J. S. Bellini,
software created based on Solange Gueiros' Solidity/JavaScript snippets
available at https://github.com/solangegueiros/DevEthereum-Course
shown during her introductory course to Ethereum given on TDC 2018 SP
(The Developer's Conference @ São Paulo).
"""
import json, os
from sanic import response, Sanic
from web3 import HTTPProvider, Web3
from web3.contract import ConciseContract
ETH_NODE_URL = os.environ.get("ETH_NODE_URL", "http://localhost:8545")
ETH_CONTRACT_ADDRESS = os.environ["ETH_CONTRACT_ADDRESS"]
# Requires Python 3.6+ in order to keep the dict order
# One can store abi directly as a string instead of dumping this,
# e.g. using the JS array from the first "web3Deploy" line in "Details"
# when infonote.sol gets compiled by http://remix.ethereum.org/
abi_list = [
{
"constant": False,
"inputs": [{"name": "i", "type": "string"}],
"name": "set",
"outputs": [],
"payable": False,
"stateMutability": "nonpayable",
"type": "function",
},
{
"constant": True,
"inputs": [],
"name": "get",
"outputs": [{"name": "", "type": "string"}],
"payable": False,
"stateMutability": "view",
"type": "function",
},
]
w3 = Web3(HTTPProvider(ETH_NODE_URL))
contract = w3.eth.contract(
address=Web3.toChecksumAddress(ETH_CONTRACT_ADDRESS),
abi=json.dumps(abi_list, separators=(",", ":")),
ContractFactoryClass=ConciseContract,
)
app = Sanic(__name__)
app.static("/", "index.html")
@app.route("/info")
async def get_info(request):
return response.text(contract.get())
@app.route("/info", methods=["POST"])
async def post_info(request):
contract.set(request.body, transact={"from": w3.eth.accounts[0]})
return response.text("Stored!")
<!DOCTYPE html>
<html>
<head>
<title>InfoNote</title>
<meta charset="UTF-8" />
<script>
document.addEventListener("DOMContentLoaded", function(){
document.getElementById("get").addEventListener("click", function (){
var xhr = new XMLHttpRequest();
xhr.open("GET", "info", true);
xhr.addEventListener("load", function(){
document.getElementById("stored").textContent = this.responseText;
})
xhr.send(null);
});
document.getElementById("set").addEventListener("click", function (){
var xhr = new XMLHttpRequest();
xhr.open("POST", "info", true);
xhr.setRequestHeader("Content-Type", "text/plain");
xhr.addEventListener("readystatechange", function(){
if(this.readyState == XMLHttpRequest.DONE && this.status == 200)
alert("Stored! Wait a little bit to have this update 'mined'.");
})
xhr.send(document.getElementById("typed").value);
});
});
</script>
<style>
button {display: block;}
</style>
</head>
<body>
<input id="typed">
<button id="set">Set</button>
<hr>
<pre id="stored"></pre>
<button id="get">Get</button>
</body>
</html>
pragma solidity ^0.4.24;
contract InfoNote {
string private info;
function set(string i) public { info = i; }
function get() public view returns (string) { return info; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment