Set Up a Server
For any smart contract, with or without an off-chain handler, the next step is to set up a server to run it. In this example, we will create a simple JSON-RPC
server using the jsonrpclib
library:
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer, SimpleJSONRPCRequestHandler
def selector(name):
nameHash = Web3.to_hex(Web3.keccak(text=name))
return nameHash[2:10]
class RequestHandler(SimpleJSONRPCRequestHandler):
rpc_paths = ('/', '/hc')
def server_loop():
server = SimpleJSONRPCServer(
('0.0.0.0', 1234), requestHandler=RequestHandler)
server.register_function(offchain_addsub2, selector("addsub2(uint32,uint32)")) # 97e0d7ba
server.serve_forever()
server_loop() # Run until killed
Here, we register our function offchain_addsub2()
. Note that the identifier passed to register_function()
is generated by the selector()
function, which creates a hashed representation of the function signature provided as an argument.
Why is that?
The bundler sends us a JSON-RPC v2
request, containing a method
identifier. This identifier is the function selector of the desired off-chain method, along with several standard parameters (the names of which are subject to change) and a payload
which contains the ABI-encoded request data:
{
"jsonrpc":"2.0",
"id":0,
"method":"97e0d7ba",
"params":{
"sk":"f27fb73f63cd38cee89c48053fe8bb3248ddb7a98ce9f45b9176d017df47d9ce",
"src_addr":"b43a2532e87583351b9024d6a6d0ba7acfa54446",
"src_nonce":"0000000000000000000000000000000000000000000003eb0000000000000003",
"oo_nonce":"0xb43a2532e87583351b9024d6a6d0ba7acfa544460000000000000003",
"payload":"00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001"
}
}
With the server set up, proceed to the following section to learn how to write our own smart contract.