github.com/kisexp/xdchain@v0.0.0-20211206025815-490d6b732aa7/cmd/clef/pythonsigner.py (about)

     1  import os,sys, subprocess
     2  from tinyrpc.transports import ServerTransport
     3  from tinyrpc.protocols.jsonrpc import JSONRPCProtocol
     4  from tinyrpc.dispatch import public,RPCDispatcher
     5  from tinyrpc.server import RPCServer
     6  
     7  """ This is a POC example of how to write a custom UI for Clef. The UI starts the
     8  clef process with the '--stdio-ui' option, and communicates with clef using standard input / output.
     9  
    10  The standard input/output is a relatively secure way to communicate, as it does not require opening any ports
    11  or IPC files. Needless to say, it does not protect against memory inspection mechanisms where an attacker
    12  can access process memory."""
    13  
    14  try:
    15      import urllib.parse as urlparse
    16  except ImportError:
    17      import urllib as urlparse
    18  
    19  class StdIOTransport(ServerTransport):
    20      """ Uses std input/output for RPC """
    21      def receive_message(self):
    22          return None, urlparse.unquote(sys.stdin.readline())
    23  
    24      def send_reply(self, context, reply):
    25          print(reply)
    26  
    27  class PipeTransport(ServerTransport):
    28      """ Uses std a pipe for RPC """
    29  
    30      def __init__(self,input, output):
    31          self.input = input
    32          self.output = output
    33  
    34      def receive_message(self):
    35          data = self.input.readline()
    36          print(">> {}".format( data))
    37          return None, urlparse.unquote(data)
    38  
    39      def send_reply(self, context, reply):
    40          print("<< {}".format( reply))
    41          self.output.write(reply)
    42          self.output.write("\n")
    43  
    44  class StdIOHandler():
    45      def __init__(self):
    46          pass
    47  
    48      @public
    49      def ApproveTx(self,req):
    50          """
    51          Example request:
    52          {
    53              "jsonrpc": "2.0",
    54              "method": "ApproveTx",
    55              "params": [{
    56                  "transaction": {
    57                      "to": "0xae967917c465db8578ca9024c205720b1a3651A9",
    58                      "gas": "0x333",
    59                      "gasPrice": "0x123",
    60                      "value": "0x10",
    61                      "data": "0xd7a5865800000000000000000000000000000000000000000000000000000000000000ff",
    62                      "nonce": "0x0"
    63                  },
    64                  "from": "0xAe967917c465db8578ca9024c205720b1a3651A9",
    65                  "call_info": "Warning! Could not validate ABI-data against calldata\nSupplied ABI spec does not contain method signature in data: 0xd7a58658",
    66                  "meta": {
    67                      "remote": "127.0.0.1:34572",
    68                      "local": "localhost:8550",
    69                      "scheme": "HTTP/1.1"
    70                  }
    71              }],
    72              "id": 1
    73          }
    74  
    75          :param transaction: transaction info
    76          :param call_info: info abou the call, e.g. if ABI info could not be
    77          :param meta: metadata about the request, e.g. where the call comes from
    78          :return:
    79          """
    80          transaction = req.get('transaction')
    81          _from       = req.get('from')
    82          call_info   = req.get('call_info')
    83          meta        = req.get('meta')
    84  
    85          return {
    86              "approved" : False,
    87              #"transaction" : transaction,
    88    #          "from" : _from,
    89  #            "password" : None,
    90          }
    91  
    92      @public
    93      def ApproveSignData(self, req):
    94          """ Example request
    95  
    96          """
    97          return {"approved": False, "password" : None}
    98  
    99      @public
   100      def ApproveExport(self, req):
   101          """ Example request
   102  
   103          """
   104          return {"approved" : False}
   105  
   106      @public
   107      def ApproveImport(self, req):
   108          """ Example request
   109  
   110          """
   111          return { "approved" : False, "old_password": "", "new_password": ""}
   112  
   113      @public
   114      def ApproveListing(self, req):
   115          """ Example request
   116  
   117          """
   118          return {'accounts': []}
   119  
   120      @public
   121      def ApproveNewAccount(self, req):
   122          """
   123          Example request
   124  
   125          :return:
   126          """
   127          return {"approved": False,
   128                  #"password": ""
   129                  }
   130  
   131      @public
   132      def ShowError(self,message = {}):
   133          """
   134          Example request:
   135  
   136          {"jsonrpc":"2.0","method":"ShowInfo","params":{"message":"Testing 'ShowError'"},"id":1}
   137  
   138          :param message: to show
   139          :return: nothing
   140          """
   141          if 'text' in message.keys():
   142              sys.stderr.write("Error: {}\n".format( message['text']))
   143          return
   144  
   145      @public
   146      def ShowInfo(self,message = {}):
   147          """
   148          Example request
   149          {"jsonrpc":"2.0","method":"ShowInfo","params":{"message":"Testing 'ShowInfo'"},"id":0}
   150  
   151          :param message: to display
   152          :return:nothing
   153          """
   154  
   155          if 'text' in message.keys():
   156              sys.stdout.write("Error: {}\n".format( message['text']))
   157          return
   158  
   159  def main(args):
   160      cmd = ["clef", "--stdio-ui"]
   161      if len(args) > 0 and args[0] == "test":
   162          cmd.extend(["--stdio-ui-test"])
   163      print("cmd: {}".format(" ".join(cmd)))
   164      dispatcher = RPCDispatcher()
   165      dispatcher.register_instance(StdIOHandler(), '')
   166      # line buffered
   167      p = subprocess.Popen(cmd, bufsize=1, universal_newlines=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
   168  
   169      rpc_server = RPCServer(
   170          PipeTransport(p.stdout, p.stdin),
   171          JSONRPCProtocol(),
   172          dispatcher
   173      )
   174      rpc_server.serve_forever()
   175  
   176  if __name__ == '__main__':
   177      main(sys.argv[1:])