Sign Up for Free

RunKit +

Try any Node.js package right in your browser

This is a playground to test code. It runs a full Node.js environment and already has all of npm’s 400,000 packages pre-installed, including liquid-tap with all npm packages installed. Try it out:

var liquidTap = require("liquid-tap")

This service is provided by RunKit and is not affiliated with npm, Inc or the package authors.

liquid-tap v0.3.3

Liquid Websocket API Client

LiquidTap Javascript Client

To manage API tokens, refer to: https://app.liquid.com/settings/api-tokens

To learn more about Liquid Api token management, see the help links below: https://help.liquid.com/connect-to-liquid-via-api

Links

Events Authentication [Troubleshooting] (#troubleshooting) [Contributing] (#contributing)

Quick Start

Install via npm or yarn:

npm install liquid-tap
yarn add liquid-tap

OR Include the library:

<script src="../dist/liquid-tap.js"></script>
import { TapClient } from "liquid-tap";

const tap = new TapClient();
const public_channel = tap.subscribe("product_cash_btcsgd_7");
public_channel.bind("updated", function(data) {
  console.log("product_cash_btcsgd_7 has been updated", data);
});

Events

EventPayloadDescription
connected{ reconnect: boolean }Fires on successful connection. Contains a boolean indicating whether this was an automatic reconnection.
disconnectedn/aFires on disconnect.
unavailablen/aFires when a connection is unavailable for any reason.
tick_received{ event: string, data: any, channel?: string }Fires on every websocket event. Contains the entire websocket payload.
authenticatedn/aFires when the websocket has successfully authenticated
authentication_failed{ message: string, attempts: number }Fires when authentication has failed. Contains a message from the server and the number of authentication attempts.
authentication_aborted{ attempts: number }Fires when the maximum number of automatic authentication retries is reached. Contains the number of attempts.

Binding to events

Callbacks

import { TapClient }, { CLIENT_EVENTS } from 'liquid-js'

var tap = new TapClient();
tap.bind(CLIENT_EVENTS.CONNECTED, function () {
  console.log('Connected!');
});
tap.bind(CLIENT_EVENTS.AUTH_SUCCESS, function () {
  console.log('Authenticated!');
});
tap.bind(CLIENT_EVENTS.AUTH_FAILURE, function () {
  console.log('Authentication Failed!');
});

Promises

var tap = new TapClient();
tap.bind(CLIENT_EVENTS.CONNECTED).then(() => {
  console.log("Connected!");
});
tap.bind(CLIENT_EVENTS.AUTH_SUCCESS).then(() => {
  console.log("Authenticated!");
});
tap.bind(CLIENT_EVENTS.AUTH_FAILURE).then(() => {
  console.log("Authentication Failed!");
});

Options

KeyTypeDefaultDescription
wsHoststring'tap.liquid.com'Tap WS host to connect to.
wsPortnumber433Port to connect to.
wssPortnumber433SSL Port to connect to.
useTlsbooleantrueShould connect using SSL.
authAuthType (see below)nullAuthentication information. See below.
appIdstring'LiquidTapClient'Arbitrary name to use in the WS url.
authenticationTimeoutnumber (ms)5000Timeout to assume authentication has failed. (Note a auth_failed event is expected)
authRetryDelaynumber (ms)200Time to wait before retrying authentication.
authRetryMaxAttemptsnumber3Maximum number of authentication retries.

Authentication

To subscribe to protected channels, the client must provide a token_id and token_secret which has permission to view those channels. The library will attempt to authenticate three times by default.

Authenticate Sequence

Before Initialization

var tap = new TapClient({
  auth: { tokenId: token_id, toeknSecret: token_secret }
});
// Refer to profile page for user_id: https://app.liquid.com/settings/profile
var protected_channel = tap.subscribe("user_<user_id>");
protected_channel.bind("updated", function(data) {
  console.log("sensitive user data has been updated", data);
});

After Initialization

The library allows the LiquidTap client to be created and subscribe to public channels, then when a protected channel is required the client can authenticate.

var tap = new TapClient();

var public_channel = tap.subscribe("product_cash_btcsgd_7");
public_channel.bind("updated", function(data) {
  console.log("product_cash_btcsgd_7 has been updated", data);
});

tap.authenticate({ tokenId: token_id, tokenSecret: token_secret });
var protected_channel = tap.subscribe("user_<user_id>");
protected_channel.bind("updated", function(data) {
  console.log("sensitive user data has been updated", data);
});

Authentication Input

The authentication can be done either by providing an API token ID and secret, JWT token, or callback.

Token ID and Secret

var tap = new TapClient({
  auth: { tokenId: token_id, tokenSecret: token_secret }
});
var tap = new TapClient();
tap.authenticate({ tokenId: token_id, tokenSecret: token_secret });

Signed JWT

var tap = new TapClient({ auth: signed_jwt });
var tap = new TapClient();
tap.authenticate(signed_jwt);

Callback (return string)

var tap = new TapClient({
  auth: ({ path }) => jwt.encode({token_id: my_token_id, path: path}, my_secret)
});

Callback (return Promise)

The authentication process inside TapClient will wait for the promise to resolve before authenticating.

const createJwtWhenReady = ({ path }) => {
  return new Promise<string>(
    (resolve) => {
        setTimeout(
          () => resolve(jwt.encode({token_id: my_token_id, path: path}, my_secret)), 
          some_wait_period
        )
    })
}
var tap = new TapClient({
  auth: createJwtWhenReady
});

TapClient will also wrap the promise to allow process order management

var tap = new TapClient();
const createJwtWhenReady = ({ path }) => {
  return new Promise<string>(
    (resolve) => {
        setTimeout(
          () => resolve(jwt.encode({token_id: my_token_id, path: path}, my_secret)), 
          some_wait_period
        )
    })
}
tap.authenticate({
  auth: createJwtWhenReady
})
.then(() => {
  // do something
})
.catch(() => {
  // some error in either generating the jwt, or the websocket request event
})

Callback (which takes another callback)

var tap = new TapClient();

// Create a service to manage nonce and JWT creation
const createJwtWhenReady = ({ path }, callback) => {
    setTimeout(
      () => {
        nonce_counter += 1;
        // this callback will return a Promise that resolves when the auth request comes back, either success or failure
        await callback(jwt.encode({token_id: my_token_id, path: path, nonce: nonce_counter }, my_secret));
      }, some_wait_period
    )
}

tap.authenticate({
  auth: createJwtWhenReady
})
.then(() => {
  // will be called after the resolver for the above JWT creator
})
.catch(() => {
  // log error
})

Troubleshooting

Open the chrome dev tools and inspect the network traffic as shown in the image below: inspecting websocket frames

Contributing

Setup

npm install

Development

npm run build:dev
npm run sample

Testing

npm test

Ensure changes are also thoroughly tested with the real world server responses.

Building

npm run build

Ensure to commit compiled assets in dist.

RunKit is a free, in-browser JavaScript dev environment for prototyping Node.js code, with every npm package installed. Sign up to share your code.
Sign Up for Free