# standard imports import logging import re import socket import uuid import json logg = logging.getLogger(__file__) def jsonrpc_request(method, params): uu = uuid.uuid4() return { "jsonrpc": "2.0", "id": str(uu), "method": method, "params": params, } class PlatformMiddleware: # id for the request is not available, meaning we cannot easily short-circuit # hack workaround id_seq = -1 re_personal = re.compile('^personal_.*') ipcaddr = None def __init__(self, make_request, w3): self.w3 = w3 self.make_request = make_request if self.ipcaddr == None: raise AttributeError('ipcaddr not set') # TODO: understand what format input params come in # single entry input gives a tuple on params, wtf... # dict input comes as [{}] and fails if not passed on as an array @staticmethod def _translate_params(params): #if params.__class__.__name__ == 'tuple': # r = [] # for p in params: # r.append(p) # return r if params.__class__.__name__ == 'list' and len(params) > 0: return params[0] return params # TODO: DRY def __call__(self, method, suspect_params): self.id_seq += 1 logg.debug('in middleware method {} params {} ipcpath {}'.format(method, suspect_params, self.ipcaddr)) if self.re_personal.match(method) != None: params = PlatformMiddleware._translate_params(suspect_params) # multiple providers is removed in web3.py 5.12.0 # https://github.com/ethereum/web3.py/issues/1701 # thus we need a workaround to use the same web3 instance s = socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM, proto=0) ipc_provider_workaround = s.connect(self.ipcaddr) logg.info('redirecting method {} params {} original params {}'.format(method, params, suspect_params)) o = jsonrpc_request(method, params[0]) j = json.dumps(o) logg.debug('send {}'.format(j)) s.send(j.encode('utf-8')) r = s.recv(4096) s.close() logg.debug('got recv {}'.format(str(r))) jr = json.loads(r) jr['id'] = self.id_seq #return str(json.dumps(jr)) return jr elif method == 'eth_signTransaction': params = PlatformMiddleware._translate_params(suspect_params) s = socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM, proto=0) ipc_provider_workaround = s.connect(self.ipcaddr) logg.info('redirecting method {} params {} original params {}'.format(method, params, suspect_params)) o = jsonrpc_request(method, params[0]) j = json.dumps(o) logg.debug('send {}'.format(j)) s.send(j.encode('utf-8')) r = s.recv(4096) s.close() logg.debug('got recv {}'.format(str(r))) jr = json.loads(r) jr['id'] = self.id_seq #return str(json.dumps(jr)) return jr elif method == 'eth_sign': params = PlatformMiddleware._translate_params(suspect_params) s = socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM, proto=0) ipc_provider_workaround = s.connect(self.ipcaddr) logg.info('redirecting method {} params {} original params {}'.format(method, params, suspect_params)) o = jsonrpc_request(method, params) j = json.dumps(o) logg.debug('send {}'.format(j)) s.send(j.encode('utf-8')) r = s.recv(4096) s.close() logg.debug('got recv {}'.format(str(r))) jr = json.loads(r) jr['id'] = self.id_seq return jr r = self.make_request(method, suspect_params) return r