Skip to content

WebSocket API

Konstantin Cyber edited this page Nov 28, 2018 · 73 revisions

KeyChain contains a WebSocket API. This API can be used to stream information from a KeyChain instance to any client that implements WebSockets. Implementations in different languages:

  • NodeJS
  • Python
  • JavaScript/HTML
  • etc

Connect your WebSocket implementation to ws://localhost:16384/.

Demo page

Here you will find a demo page that connects to WebSocket.

Message format

Each WebSocket API message is a JSON serialized object containing a command with the corresponding parameters.

For full comprehensive descriptions of the commands, acceptable parameters and values, go to the Protocol.

WebSocket integration guide

NodeJS integration example

The following will show the usage of websocket connections. We make use of the wscat application available via npm:

npm install -g wscat A non-restricted call against a full-node would take the form:

wscat -c ws://127.0.0.1:8090 > {"id":1, "method":"call", "params":[0,"get_accounts",[["1.2.0"]]]}

Successful Calls

The API will return a properly JSON formated response carrying the same id as the request to distinguish subsequent calls.

{
 "id":1,
 "result":  ..data..
}

Errors

In case of an error, the resulting answer will carry an error attribute and a detailed description:

{
  "id": 0
  "error": {
    "data": {
      "code": error-code,
      "name": " .. name of exception .."
      "message": " .. message of exception ..",
      "stack": [ .. stack trace .. ],
    },
    "code": 1,
  },
}

JavaScript integration example

Before you proceed with the integration, you need to download and install KeyChain.

After installing KeyChain you will need to create a web page that connects to WebSocket through localhost.

Below is an example of how to write a simple HTML page in JavaScript.

<!DOCTYPE html>
<html>
  <head>
    <title>Keychain test page</title>
    <link rel="stylesheet" href="./spectre.min.css">
    <style>
      button {
        width: 100%;
      }
    </style>
  </head>
  <body>
    <h1 class="mx-2">Keychain test page</h1>
    <div class="container">
      <div class="columns m-1">        
        <div class="column col-2 ">
          <button class="btn btn-primary" id="btn_LIST">List</button>
        </div>
      </div>
      <div class="columns m-1">
        <div class="column col-2">
          <button class="btn btn-primary" id="btn_LOCK">Lock</button>
        </div>  
      </div>
      <div class="columns m-1">
        <div class="column col-2">
          <button class="btn btn-primary" id="btn_UNLOCK">Unlock</button>
        </div>
        <div class="column col-8">
          <input type="text" class="form-input" placeholder="test1@be5f6e75878b84ba" id="input_UNLOCK">
        </div>
      </div>
      <div class="columns m-1">
        <div class="column col-2">
          <button class="btn btn-primary input-group-btn" id="btn_SET_UNLOCK_TIME">Set unlock time</button>
        </div>  
        <div class="column col-8">  
          <input type="text" class="form-input" placeholder="300" id="input_SET_UNLOCK_TIME">
        </div>
      </div>
      <div class="columns m-1">
        <div class="column col-2">
          <button class="btn btn-primary input-group-btn" id="btn_PUBLIC_KEY">Public key</button>
        </div>
        <div class="column col-8">
          <input type="text" class="form-input" placeholder="test1@be5f6e75878b84ba" id="input_PUBLIC_KEY">
        </div>
      </div>
      <div class="columns m-1">
        <div class="column col-2">
          <button class="btn btn-primary input-group-btn" id="btn_SIGN_HEX">Sign hex</button>
        </div>  
        <div class="column col-8">  
          <input type="text" class="form-input" placeholder="test1@be5f6e75878b84ba" id="input_SIGN_HEX">
        </div>
      </div>
      <div class="columns m-1">
        <div class="column col-2">
          <button class="btn btn-primary input-group-btn" id="btn_SIGN_HASH">Sign hash</button>
        </div>
        <div class="column col-8">
          <input type="text" class="form-input" placeholder="test1@be5f6e75878b84ba" id="input_SIGN_HASH">
        </div>
      </div>
      <div class="columns m-1">
        <div class="column col-2">
          <button class="btn btn-primary input-group-btn" id="btn_CREATE">Create</button>
        </div>
      </div>
    </div>
    <div class="container">
      <div class="columns">
        <div class="column col-6">
          <label class="form-label" for="request">Request</label>
          <textarea class="form-input" id="request" placeholder="{}" rows="9"></textarea>
        </div>
        <div class="column col-6">
          <label class="form-label" for="response">Response</label>
          <textarea class="form-input" id="response" placeholder="{}" rows="9"></textarea>
        </div>
      </div>
    </div>
 
    <script>
      const ws = new WebSocket('ws://localhost:16384/');

      ws.onopen = function() {
        document.body.style.backgroundColor = '#cfc';
      };
      ws.onclose = function() {
        document.body.style.backgroundColor = null;
      };
      ws.onmessage = function(event) {
        document.getElementById('response').textContent = JSON.stringify(JSON.parse(event.data), undefined, 2);
      };
      
      const commands = {
        UNLOCK: {
          command: "unlock",
          params: {
            keyname: null
          }
        },
        SET_UNLOCK_TIME: {
          command: "set_unlock_time",
          params: {
            seconds: null
          }
        },
        PUBLIC_KEY: {          
          command: "public_key",
          params: {
            keyname: null
          }
        },
        SIGN_HEX: {
          command: "sign_hex",
          params: {
            chainid: "03",
            transaction: "eb0885098bca5a00825208948ec6977b1255854169e5f9f8f163f371bcf1ffd287038d7ea4c6800080038080",
            blockchain_type: "ethereum",
            keyname: null
          }
        },
        SIGN_HASH: {
          command: "sign_hash",
          params: {
            sign_type: "VRS_canonical",
            hash: "fe5e4a8974715e20f47c8bb609547c9e66b0b9e31d521199b3d8d6af6da74cb1",
            keyname: null
          }
        },
        CREATE: {
          command: "create",
          params: {
            keyname: "test1",
            encrypted: true,
            curve: "secp256k1",
            cipher: "aes256"
          }
        },
        LIST: {
          command: "list"
        },
        LOCK: {
          command: "lock"
        }
      }

      window.onload = function () {
        attachListener('UNLOCK', 'keyname');
        attachListener('SET_UNLOCK_TIME', 'seconds');
        attachListener('PUBLIC_KEY', 'keyname');
        attachListener('SIGN_HEX', 'keyname');
        attachListener('SIGN_HASH', 'keyname');
        attachListener('CREATE');
        attachListener('LIST');
        attachListener('LOCK');
      }
       
      function attachListener(commandName, paramName) {
        document.getElementById(`btn_${commandName}`).addEventListener('click', function() {
          if (paramName) {
            const inputValue = document.getElementById(`input_${commandName}`).value;
            commands[commandName].params[paramName] = inputValue;
          }
          const data = JSON.stringify(commands[commandName], undefined, 2);
          document.getElementById('request').value = data;
          ws.send(data);
        });
      }
    </script>
  </body>
</html>

Save to demo.html and open this page through the browser. Or you can fin

Python integration example

Requirements

Python ≥ 3.6

NB: This documentation is written for Python ≥ 3.6.

1. Install websocket with:

Pip install websockets

Response example

Successfully installed websockets-7.0