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.

Last updated