1. Home
  2. Article Catalog
  3. How to implement Refinitiv Real-Time - Optimized Node.js application with TypeScript part 2: WebSocket

Article

How to implement Refinitiv Real-Time - Optimized Node.js application with TypeScript part 2: WebSocket

Wasin Waeosri
Developer Advocate Developer Advocate

Overview

Update: January 2021

Refinitiv Data Platform (RDP) gives you seamless and holistic access to all of the Refinitiv content (whether real-time or non-real-time, analytics or alternative datasets), commingled with your content, enriching, integrating, and distributing the data through a single interface, delivered wherever you need it.

As part of the Refinitiv Data Platform, Refinitiv Real-Time - Optimized (formerly known as ERT in Cloud) gives you access to best in class Real-Time market data delivered in the cloud. Refinitiv Real-Time - Optimized is a new delivery mechanism for RDP, using the AWS (Amazon Web Services) cloud. Once a connection to RDP is established using Refinitiv Real-Time - Optimized, data can be retrieved using Websocket API for Pricing Streaming and Real-Time Services aka WebSocket API.

This article is the second part of how to implement the Refinitiv Real-Time - Optimized Node.js application with TypeScript language articles. The first article shows how to authenticate and get VIPs information via RDP REST APIs. This second part article focuses on how to implement a Node.js TypeScript application to connect and consume streaming Market Price data from Refinitiv Real-Time - Optimized via the WebSocket connection. The application source codes are implemented in TypeScript language and will be compiled to a readable JavaScript file and run in a console with Node.js runtime environment.

*Note: The application functionalities are based on Refinitiv Real-Time - Optimized market_price_edpgw_service_discovery.py Python example. Access to the Refinitiv RDP and Refinitiv Real-Time - Optimized are required.

AnchorTypeScript Overview

TypeScript is an open-source programming language developed and maintained by Microsoft. The language lead architect is Anders Hejlsberg, lead architect of C# and creator of Delphi and Turbo Pascal. TypeScript is a typed superset of JavaScript that compiles to readable, standards-based JavaScript. The syntax is designed for application-scale JavaScript by adding optional types, classes, modules, ECMAScript 2015 features, and future proposals to JavaScript. TypeScript supports tools for large-scale JavaScript applications for any browser, for any host, on any OS. TypeScript is a first-class programming language in Microsoft Visual Studio and Angular web application platform. It also supported by various application frameworks like ReactNodeJS and Express frameworkASP.Net CoreVue.js, and more.

RDP and Refinitiv Real-Time - Optimized Application Implementation Process

The application requires the following steps to authentication and consume data from RDP and Refinitiv Real-Time - Optimized

  1. Send a HTTP POST request message with username (Machine ID) and password information to RDP Authentication service to obtain access token, refresh token, expiration time and scope information
  2. Send a HTTP GET request message with access token to RDP Realtime Service Discovery service to get lists of Refinitiv Real-Time - Optimized WebSocket streaming server endpoints, ports and location information (VIPs)
  3. Connect to Refinitiv Real-Time - Optimized WebSocket endpoint from step (2)
  4. Once a WebSocket connection is established, sends a JSON Login request message with access token Refinitiv Real-Time - Optimized WebSocket server
  5. Once the Login request message is accepted by Refinitiv Real-Time - Optimized WebSocket server, the application can send item subscription request messages to Refinitiv Real-Time - Optimized endpoint.
  6. Handle asynchronous responses and status changes when they occur, including “pings” and connection failures.
  7. Re-issue RDP Authentication service before token expiration to keep the session opens.
  8. Once the application receives a new access token, application must re-send a new JSON Login request message with a new access token and refresh attribute value false in the JSON message to Refinitiv Real-Time - Optimized WebSocket server
  9. All current item streams will be remain opened

Refinitiv Real-Time - Optimized WebSocket Application Code Walkthrough

The main application is market_price_edpgw_service_discovery.ts application file. All WebSocket communication logic are implemented in edprt_websocket_controller.ts WSConnectionController class file. The applications use Node.js EventEmitter class to asynchronous communicate between each other. The main application registers for specific WSConnectionController's events to receive JSON OMM messages with Refinitiv Real-Time - Optimized service.

The edprt_websocket_controller.ts WSConnectionController class uses Node.js ws module to make a WebSocket connection with Refinitiv Real-Time - Optimized.

All WebSocket JSON messages structure are defined in json_msg_interface.ts interface file.

Anchorjson_msg_interface.ts Code Walkthrough: Define JSON messages interface

Firstly, we define interfaces for all JSON OMM messages in the json_msg_interface.ts file. The TypeScript's interfaces feature helps developers type-checking their variables and data in the implementation time to avoid data type error in a final JavaScript application. We use export keyword to let these interfaces can be used by other modules.

    	
            

// Interface for Elektron WebSocket Login domain JSON message

export interface IWS_Login {

    ID: number;

    Domain: string;

    Key: IWS_LoginKey;

    Refresh?: boolean;

}

 

// Interface for Elektron WebSocket Login domain's Key attribute JSON message

// Name and NameType attributes are optional

export interface IWS_LoginKey {

    Elements: IWS_LoginKeyElements;

    Name?: string;

    NameType?: string;

}

 

// Interface for Elektron WebSocket Login domain's Key's Elements attribute JSON message

// AuthenticationToken attributes is optional

export interface IWS_LoginKeyElements {

    ApplicationId: string;

    Position: string;

    AuthenticationToken?: string;

}

The interfaces include the Login request, Item request and Pong messages.

    	
            

// Interface for Elektron WebSocket Market Price domain item request JSON message

export interface IWS_ItemRequestMsg {

    ID: number;

    Domain?: string;

    Key: IWS_ItemRequestKey;

}

 

// Interface for Elektron WebSocket  Market Price domain item request's key attribute JSON message

// service name is an optional 

export interface IWS_ItemRequestKey {

    Name: string;

 

    Service?: string;

}

 

//Interface for Elektron WebSocket Pong message (HB message between consumer and ADS server) 

export interface IWS_Pong {

    readonly Type: string;

}

Anchoredprt_websocket_controller.ts Code Walkthrough: Initiate the class and connect to Refinitiv Real-Time Optimized

Firstly, we import all required interfaces and Node.js modules in the edprt_websocket_controller.ts file.

    	
            

import * as WebSocket from "ws";

import * as EventEmitter from "events";

 

import { IWS_Login } from "./json_msg_interface";

import { IWS_ItemRequestMsg } from "./json_msg_interface";

import { IWS_Pong } from "./json_msg_interface";

import { IDataAuthen } from "./json_msg_interface";

Next, we create a WSConnectionController class in the edprt_websocket_controller.ts file. This class handles all WebSocket operations between the main application class (market_price_edpgw_service_discovery.ts file) and Refinitiv Real-Time Optimized server. We use export keyword to let this class can be used by other modules/classes. We create an emitter variable as an EventEmitter object for communicating with the main class.

    	
            

export { WSConnectionController };

 

class WSConnectionController {

 

    private emitter: EventEmitter;

    private readonly ws_protocol: string = 'tr_json2';

    private readonly loginDomain: string = "Login";

    private readonly loginID: number = 1;

    private ws_session: any = null;

    private session_name: string;

    private auth_obj: IDataAuthen = {

        access_token: '',

        refresh_token: '',

        expires_in: '',

        transport: 'websocket',

        dataformat: 'tr_json2',

        position: '',

        appId: '256',

    };

 

    constructor(emitter: EventEmitter, session_name: string) {

        this.emitter = emitter;

        this.session_name = session_name;

    }

 

}

Next, we implement a connect() function to establish a WebSocket connection with Refinitiv Real-Time Optimized endpoint with ws module.

    	
            

/ Initiate WebSocket connection to  WebSocket server

public connect(url: string, auth_obj: IDataAuthen) {

    console.log(`${this.session_name} ws_connect to ${url}`);

    this.ws_session = new WebSocket(url, this.ws_protocol);

    this.ws_session.onopen = this.onOpen;

    this.ws_session.onmessage = this.onMessage;

    this.ws_session.onerror = this.onError;

    this.ws_session.onclose = this.onClose;

 

    this.auth_obj = auth_obj;

}

 

// Indicates that the connection is ready to send and receive messages

private onOpen = (event: any) => {

    //establish connection success

}

 

// An event listener to be called when a message is received from the server

private onMessage = (event: any) => {

    //handle incomimg messages

}

 

// An event listener to be called when an error occurs. This is a simple event named "error".

private onError = (event: any) => {

    console.log(`Error on ${this.session_name}: ${JSON.stringify(event.data)}`);

}

 

// An event listener to be called when the WebSocket connection's readyState changes to CLOSED.

private onClose = (event: any) => {

    console.log(JSON.stringify(event.data));

}

Anchoredprt_websocket_controller.ts Code Walkthrough: Login process

Once the class success establish a connection with Refinitiv Real-Time Optimized server, the onOpen() callback function will be trigger. We implement the _send_login_request() function to send the OMM Login request message to Refinitiv Real-Time Optimized in JSON format. For Refinitiv Real-Time Optimized connection, the following attributes and values are required in a JSON messages.

  • Key.NameType: AuthnToken
  • Key.Elements.AuthenticationToken: RDP Access Token
  • Key.Elements.ApplicationId: The ID of the application to which the connection is made.
  • Key.Elements.Position: The IP address position of the application logging in.

The WSConnectionController class receives these RDP authentication information from the main application's auth_obj object as a connect() function parameter.

    	
            

// Indicates that the connection is ready to send and receive messages

private onOpen = (event: any) => {

    console.log(`WebSocket successfully connected for ${this.session_name}, sedning login request message`);

    this._send_login_request();

}

 

// send JSON OMM Login request message to Refinitiv Real-Time - Optimized WebSocket server

private _send_login_request(refresh = false) {

    const login_msg: IWS_Login = {

        ID: this.loginID,

        Domain: this.loginDomain,

        Key: {

            NameType: 'AuthnToken',

            Elements: {

                ApplicationId: '',

                Position: '',

            }

        },

    };

 

    login_msg['Key']['Elements']['ApplicationId'] = this.auth_obj.appId;

    login_msg['Key']['Elements']['Position'] = this.auth_obj.position;

    login_msg['Key']['Elements']['AuthenticationToken'] = this.auth_obj.access_token;

 

    this.ws_session.send(JSON.stringify(login_msg));

    console.log(`Sent on ${this.session_name}:`);

    console.log(JSON.stringify(login_msg, null, 2));

}

Anchoredprt_websocket_controller.ts Code Walkthrough: Handling Login Refresh response message

All WebSocket messages (Refresh, Update, Status, etc) from the Refinitiv Real-Time Optimized server will be available via WebSocket.onMessage() callback function. We implement this onMessage() callback function to parse incoming messages into JSON format, then process each message via an internal processMessage() function.

The processMessage() function checks if incoming message type is not a Ping message, it uses EventEmitter to send that message to "EDPRTWS_onMessage" event listener in the main application (market_price_edpgw_service_discovery.ts file). In this phase, it will send a Login Refresh message to the main application.

We will handle the Ping message later.

    	
            

// An event listener to be called when a message is received from the server

private onMessage = (event: any) => {

 

    const parsedMsg = JSON.parse(event.data.toString());

    //console.log(`incoming WS message is ${JSON.stringify(parsedMsg, null, 2)}`);

    for (let msg of parsedMsg) {

        this.processMessage(msg);

    }

}

 

// Process incoming JSON OMM Message 

private processMessage = (msg: any) => {

    const msgType: string = msg.Type;

 

    if (msgType === 'Ping') { //  WebSocket Ping message

       //Elektron WebSocket heatbeat process

    } else {

        // Send incoming message(s) to a main class

        this.emitter.emit('EDPRTWS_onMessage', msg, this.session_name);

    }

 

}

We will describe how market_price_edpgw_service_discovery.ts handles the Login Response message in later section.

Anchoredprt_websocket_controller.ts Code Walkthrough: Market Price item request

Once the application receives a Login Refresh message from Refinitiv Real-Time Optimized, the application is ready for subscribing data from Refinitiv Real-Time Optimized.

We implement a sendMarketPriceRequest() function in WSConnectionController class to operate the Market Price item request from the main application. This function creates a JSON OMM item request message as an item_request_msg object and sends it to Refinitiv Real-Time Optimized via WebSocket.send() function.

    	
            

// Send a Market Price JSON OMM request message to WebSocket server

public sendMarketPriceRequest(itemname: string) {

    const itemID: number = this.loginID + 1;

 

    const item_request_msg: IWS_ItemRequestMsg = {

        ID: itemID,

        Key: {

            Name: itemname,

        }

    };

 

    this.ws_session.send(JSON.stringify(item_request_msg));

    console.log(`Sent on ${this.session_name}:`);

    console.log(JSON.stringify(item_request_msg, null, 2));

}

This item_request_msg object will be compiled to a standard Item Request JSON message in a compiled JavaScript market_price_edpgw_service_discovery.js file.

Anchoredprt_websocket_controller.ts Code Walkthrough: Handle incoming data, status and Handshake messages

All messages (Refresh, Update, Status, etc) from the Refinitiv Real-Time Optimized WebSocket server will be available via WebSocket.onMessage() callback function. This controller class just parses those messages into JSON format and sends them to a main application via "EDPRTWS_onMessage" event listener to process further business logic.

The Ping and Pong messages are the handshake message ({ "Type": "Ping" } and { "Type": "Pong" }) between the Refinitiv Real-Time Optimized server and client for monitoring a connection health. Refinitiv Real-Time Optimized periodically sends Ping message to applications and applications must be prepared to send Pong messages as a response to any Ping message they receive.

This controller class receives the Ping message via WebSocket.onMessage() callback function. We modify this function to handle a handshake process for the applcaition by detecting an incoming Ping message, then sends the Pong message back to Refinitiv Real-Time Optimized server.

    	
            

// An event listener to be called when a message is received from the server

private onMessage = (event: any) => {

 

    const parsedMsg = JSON.parse(event.data.toString());

    //console.log(`incoming WS message is ${JSON.stringify(parsedMsg, null, 2)}`);

    for (let msg of parsedMsg) {

        this.processMessage(msg);

    }

}

 

// Process incoming JSON OMM Message 

private processMessage = (msg: any) => {

    const msgType: string = msg.Type;

 

    if (msgType === 'Ping') { // WebSocket Ping message

       console.log(`RECEIVED on ${this.session_name} ${JSON.stringify(msg, null, 2)}`);

       this.sendPong(); // Send WebSocket Pong message back

    } else {

        // Send incoming message(s) to a main class

        this.emitter.emit('EDPRTWS_onMessage', msg, this.session_name);

    }

}

 

// Create the client PONG message  and send it to WebSocket server

private sendPong = () => {

    const pong: IWS_Pong = { Type: "Pong" };

    console.log(`Sent on ${this.session_name}: ${JSON.stringify(pong, null, 2)}`);

    this.ws_session.send(JSON.stringify(pong));

}

Anchormarket_price_edpgw_service_discovery.ts application: Initialize WebSocket connection

Let get back to a main application implementation (market_price_edpgw_service_discovery.ts file). The main application utlizes RESTConnectionController and WSConnectionController classes to communication to RDP REST and Refinitiv Real-Time Optimized services. This main application receives all messages (except a handshake message) from Refinitiv Real-Time Optimized, then process a business logic on those messages.

Firstly we import all require mododules and classes including WSConnectionController class at a begining of the class. The application creates two WSConnectionController objects for a hot-standby feature.

    	
            

// market_price_edpgw_service_discovery.ts

 

import * as EventEmitter from "events";

import { IDataAuthen } from "./json_msg_interface";

import { RESTConnectionController } from "./edp_rest_controller";

import { WSConnectionController } from "./edprt_websocket_controller";

 

// initiate EventEmitter class for asynchronous sending and receiving "events" between each class  

class MyEmitter extends EventEmitter { }

const myEmitter: MyEmitter = new MyEmitter();

 

// WebSocket and REST controller classes

let ws_app: WSConnectionController;

let ws_app2: WSConnectionController;

Next, we decare all WebSocket and Refinitiv Real-Time Optimized relate variables such as an item name, Refinitiv Real-Time Optimized hosts list, WebSocket ports list, etc.

    	
            

const ip: any = require("ip");

auth_obj.position = ip.address();

let itemname: string = '/EUR=';

 

let WS_URL: string = '';

 

let hostList: string[] = [];

let portList: string[] = [];

Next, we parse user's input command line arguments with NPM optimist module. The application lets user specific an interested item name in a RIC (Reuters instrument code) format via a --ricparameter. The application also support a hot-standby feature via a --hotstandby parameter.

    	
            

const argv = require("optimist").argv; // For getting command line arguments 

 

// get command line arguments for setting application parameters

 

if (argv.ric) {

    itemname = argv.ric.toString();

}

if (argv.hotstandby) {

    hotstandby = true;

}

if (argv.help) {

    console.log('Usage: $>node market_price_edpgw_service_discovery.js [--app_id app_id] [--user user] [--password password] [--position position] [--auth_hostname auth_hostname] [--auth_port auth_port] [--scope scope] [--ric ric] [--hotstandby] [--help]');

    process.exit();

}

Then we initialize the WSConnectionController object with the Emitter object and a session name. If user choose a hot-standby mode, it will connect to two Refinitiv Real-Time Optimized WebSocket servers in the same time, so we create two WSConnectionController objects with different session name ("session1" and "session2").

    	
            

// Initiate WebSocket controller class(es)

ws_app = new WSConnectionController(myEmitter, 'session1');

if (hotstandby) {

    ws_app2 = new WSConnectionController(myEmitter, 'session2');

}

We create the hostList and portList array variables in the "EDPREST_getServiceDiscoverySuccess" event callback which we get Refinitiv Real-Time Optimized VIPs endpoints information (location, port, endpoint, etc) from RDP Streaming Service Discovery. Please note that a hot-standby application requires endpoints from different location (availability zone in AWS term). The application then selects the WebSocket hostList and Port from the VIPs nodes that contain only one location (node['location'].length === 1).

    	
            

// Get EDP Pricing Service Discovery information, then initiates WebSocket connection

myEmitter.on('EDPREST_getServiceDiscoverySuccess', (event) => {

    console.log(`EDP-GW Service discovery succeeded. RECEIVED: ${JSON.stringify(event, null, 2)}`);

    for (let node of event['services']) {

        if (!hotstandby) {

            if (node['location'].length === 2) {

                hostList.push(node['endpoint']);

                portList.push(node['port']);

                break;

            }

        } else {

            if (node['location'].length === 1) {

                hostList.push(node['endpoint']);

                portList.push(node['port']);

            }

        }

    }

}

Then We create a WebSocket endpoint URL in a wss://${hostList[index]}:${portList[index]}/WebSocket string format for the hostList and portList arrays. We pass this variable to the WSConnectionController.connect() function to initialize a WebSocket connection.

    	
            

// Get RDP Pricing Service Discovery information, then initiates WebSocket connection

myEmitter.on('EDPREST_getServiceDiscoverySuccess', (event) => {

    // Construct portList and hostList arrays

    for (let node of event['services']) {

        // Please see Above code.

    }

 

    // Create Refinitiv Real-Time - Optimized WebSocket server 1 URL

    WS_URL = `wss://${hostList[0]}:${portList[0]}/WebSocket`;

    console.log('Receive RDP-RT Service Endpoint and Port, init WebSocket connection for session 1');

    // Initiate Refinitiv Real-Time - Optimized WebSocket connection for session 1

    ws_app.connect(WS_URL, auth_obj);

 

    if (hotstandby) { // Hot Standby case

        // Create Refinitiv Real-Time - Optimized WebSocket server 2 URL

        WS_URL = `wss://${hostList[1]}:${portList[1]}/WebSocket`;

        console.log('Receive RDP-RT Service Endpoint and Port, init WebSocket connection for session 2');

        // Initiate Refinitiv Real-Time - Optimized WebSocket connection for session 1

        ws_app2.connect(WS_URL, auth_obj);

    }

 

});

Anchormarket_price_edpgw_service_discovery.ts application: Handle Login Refresh Response message

The WSConnectionController class just receives incoming data from Refinitiv Real-Time Optimized and sends it to the main application as it is via the "EDPRTWS_onMessage" event callback function. The main application is responsible for managing a business logic on each incomimg message.

When the application receives a Login Refresh response message (a JSON message with "Type":"Refresh and "Domain":"Login" properties), it means the application is ready for subscribing data from Refinitiv Real-Time Optimized server. The application calls a WSConnectionController.sendMarketPriceRequest() function to send the Market Price request message to Refinitiv Real-Time Optimized server.

If the application receives a Status Response message (a JSON message with "Type":"Status property), it prints that message to a console.

    	
            

// Receive incoming messages from Refinitiv Real-Time - Optimized WebSocket server

myEmitter.on('EDPRTWS_onMessage', (event, session) => {

 

    const msg = event;

    const msgType: string = msg.Type;

    switch (msgType) {

        case 'Refresh': {

            if (msg.Domain) {

                if (msg.Domain === 'Login') {

                    console.log(`Receive Login Refresh Message on ${session}: ${JSON.stringify(msg, null, 2)}`);

 

                    // Receive a Login Refresh message from WebSocket, subscribes item to Refinitiv Real-Time - Optimized

                    console.log(`Sending Market Price request on ${session} for ${itemname} item`);

                    ws_app.sendMarketPriceRequest(itemname);

 

                    // Hot Standby case, subscribes item for session 2

                    if (hotstandby && session === 'session2') {

                        ws_app2.sendMarketPriceRequest(itemname);

                    }

            break;

        }

        case 'Status': { // Receive a Status response message from WebSocket

            console.log(`Receive Status Message on ${session}: ${JSON.stringify(msg, null, 2)}`);

            break;

        }

    }

});

Anchormarket_price_edpgw_service_discovery.ts application: Handle Market Price Response messages

All Market Price response messages (Refresh, Update and Status) will be available via the the "EDPRTWS_onMessage" event callback function. The application just prints incoming messages as it is in a console.

Please note that the "Domain" attribute for the Market Price domain data is absent in all JSON messages between client and server.

    	
            

// Receive incoming messages from Refinitiv Real-Time - Optimized WebSocket server

myEmitter.on('EDPRTWS_onMessage', (event, session) => {

 

    const msg = event;

    const msgType: string = msg.Type;

    switch (msgType) {

        case 'Refresh': {

            if (msg.Domain) {

                if (msg.Domain === 'Login') {

                    // item request process    

                } 

            } else { // Receive a Market Price domain item Refresh message from WebSocket

                console.log(`Receive Market Price Refresh Message on ${session}: ${JSON.stringify(msg, null, 2)}`);

            }

            break;

        }

        case 'Update': { // Receive an item Update message from WebSocket

            console.log(`Receive Update Message on ${session}: ${JSON.stringify(msg, null, 2)}`);

            break;

        }

        case 'Status': { // Receive a Status response message from WebSocket

            console.log(`Receive Status Message on ${session}: ${JSON.stringify(msg, null, 2)}`);

            break;

        }

    }

});

AnchorApplication Setup

The project source code is available at GitHub page. You can get it via the following git command

    	
            
$>git clone git@github.com:Refinitiv-API-Samples/Example.ERT.TypeScript.NodeJS.MarketPrice.git

This example requires the following dependencies softwares and runtime

  1. Node.js runtime - version 11.4.0 or higher.
  2. npm package manager (included in Node.js)
  3. TypeScript compiler (will be installed via npm install command)
  4. Webpack JavaScript module bundler (will be installed via npm install command)

please check the README.md in the source code project for more detail.

The RDP/Refinitiv Real-Time - Optimized credentials (a username must be a Machine ID) are required to run this example. Please contact your Refinitiv's representative to help you to access RDP/Refinitiv Real-Time - Optimized account and services. You will receive your Machine ID as a user name and a link to activate your machine account and set your password via the Welcome Email that you receive when you subscribe to Refinitiv Real-Time - Optimized.

AnchorHow to run this example

1.    Unzip or download the example project folder into a directory of your choice

2.    Run $> npm install command in the command prompt to install all the dependencies required to run the sample in a subdirectory called node_modules/.

3.    If the machine is behind a proxy server, you need to configure Node.js uses proxy instead of a direct HTTP connection via the following command in a command prompt:

    	
            
set https_proxy=http://<proxy.server>:<port>

4.    Run $> npx webpack command in the command prompt to build and compile all TypeScript files in src folder into JavaScript file in ./dist/ folder.

5.    In a command prompt, go to ./dist/ folder and run market_price_edpgw_service_discovery.js Node.js application with the following command. 

    	
            
$> node market_price_edpgw_service_discovery.js --user <Your Refinitiv Real-Time Optimized Machine ID> --password <Your Refinitiv Real-Time Optimized password>

6.    Upon execution, you will be presented with authentication and Refinitiv Real-Time Optimized Service discovery processes via RDP Gateway REST API.

    	
            

Sending authentication request with password to https://api.refinitiv.com:443/auth/oauth2/v1/token

    HTTP Request: RDP-GW Authentication success

    RDP-GW Authentication succeeded. RECEIVED: {

    "access_token": "<Access Token>",

    "refresh_token": "<Refresh Token>",

    "expires_in": "300",

    "scope": "trapi.streaming.pricing.read",

    "token_type": "Bearer"

    }

    Sending RDP-GW service discovery request to https://api.refinitiv.com/streaming/pricing/v1/

    HTTP Request: RDP-GW service discovery success

    RDP-GW Service discovery succeeded. RECEIVED: {

    "services": [

        {

        "port": 443,

        "location": [

            "us-east-1a",

            "us-east-1b"

        ],

        "provider": "aws",

        "transport": "websocket",

        "endpoint": "amer-3-t3.streaming-pricing-api.refinitiv.com",

        "dataFormat": [

            "tr_json2"

        ]

        },

        {

        "port": 443,

        "location": [

            "us-east-1b"

        ],

        "provider": "aws",

        "transport": "websocket",

        "endpoint": "amer-2-t3.streaming-pricing-api.refinitiv.com",

        "dataFormat": [

            "tr_json2"

        ]

        },

        {

        "port": 443,

        "location": [

            "us-east-1a"

        ],

        "provider": "aws",

        "transport": "websocket",

        "endpoint": "amer-1-t3.streaming-pricing-api.refinitiv.com",

        "dataFormat": [

            "tr_json2"

        ]

        }

    ]

    }

7.    Then the application initials WebSocket connection between the application and Refinitiv Real-Time Optimized, then sends a Login Request message to Refinitiv Real-Time Optimized to start OMM conversation.

    	
            

Receive RDP-RT Service Endpoint and Port, init WebSocket connection for session 1

    session1 ws_connect to wss://amer-1-t3.streaming-pricing-api.refinitiv.com:443/WebSocket

    WebSocket successfully connected for session1, sending login request message

    Sent on session1:

    {

    "ID": 1,

    "Domain": "Login",

    "Key": {

        "NameType": "AuthnToken",

        "Elements": {

        "ApplicationId": "256",

        "Position": "10.42.68.162",

        "AuthenticationToken": "<Access Token>"

        }

    }

    }

    Receive Login Refresh Message on session1: {

    "ID": 1,

    "Type": "Refresh",

    "Domain": "Login",

    "Key": {

        "Name": "ABCDEFG....",

        "Elements": {

        "AllowSuspectData": 1,

        "ApplicationId": "256",

        "ApplicationName": "ADS",

        "AuthenticationErrorCode": 0,

        "AuthenticationErrorText": {

            "Type": "AsciiString",

            "Data": null

        },

        "AuthenticationTTReissue": 1541151067,

        "Position": "10.42.68.162",

        "ProvidePermissionExpressions": 1,

        "ProvidePermissionProfile": 0,

        "SingleOpen": 1,

        "SupportEnhancedSymbolList": 1,

        "SupportOMMPost": 1,

        "SupportPauseResume": 0,

        "SupportStandby": 0,

        "SupportBatchRequests": 7,

        "SupportViewRequests": 1,

        "SupportOptimizedPauseResume": 0

        }

    },

    "State": {

        "Stream": "Open",

        "Data": "Ok",

        "Text": "Login accepted by host ads-premium-az2-green-4-main-prd.use1-az2."

    },

    "Elements": {

        "PingTimeout": 30,

        "MaxMsgSize": 61430

    }

    }

8.    Onces Refinitiv Real-Time Optimized server accept a Login request, the application subcribes data and display all incoming messages in a console.

    	
            

Sending Market Price request on session1 for EUR= item

Sent on session1:

{

"ID": 2,

"Key": {

    "Name": "EUR="

}

}

Receive Market Price Refresh Message on session1: {

"ID": 2,

"Type": "Refresh",

"Key": {

    "Service": "ELEKTRON_DD",

    "Name": "EUR="

},

"State": {

    "Stream": "Open",

    "Data": "Ok",

    "Text": "*All is well"

},

"Qos": {

    "Timeliness": "Realtime",

    "Rate": "JitConflated"

},

"PermData": "AwEBITw=",

"SeqNumber": 57968,

"Fields": {

    "PROD_PERM": 213,

    "RDNDISPLAY": 153,

    "DSPLY_NAME": "SEB          STO",

    "TIMACT": "09:26:00",

    "NETCHNG_1": 0.0027,

    "HIGH_1": 1.1443,

    "LOW_1": 1.1391,

    "CURRENCY": "USD",

    "ACTIV_DATE": "2018-11-02",

    "OPEN_PRC": 1.1406,

    "HST_CLOSE": 1.1407,

    "BID": 1.1434,

    "BID_1": 1.1434,

    "BID_2": 1.1434,

    "ASK": 1.1437,

    "ASK_1": 1.1437,

    "ASK_2": 1.1438,

    "ACVOL_1": 65275,

    ...

    "BIDLO4_MS": "01:39:46.558",

    "BIDLO5_MS": "01:13:15.537",

    "MIDHI1_MS": "07:14:48.083",

    "MIDLO1_MS": "01:52:48.513",

    "BID_HR_MS": "09:00:00.21"

}

}

Receive Update Message on session1: {

"ID": 2,

"Type": "Update",

"UpdateType": "Unspecified",

"DoNotConflate": true,

"Key": {

    "Service": "ELEKTRON_DD",

    "Name": "EUR="

},

"SeqNumber": 57998,

"Fields": {

    "BID": 1.1435,

    "PRIMACT_1": 1.1435,

    "ASK": 1.1438,

    "SEC_ACT_1": 1.1438,

    "VALUE_DT1": "2018-11-02",

    "VALUE_TS1": "09:26:11",

    "TIMACT": "09:26:00",

    "NETCHNG_1": 0.0028,

    "ACTIV_DATE": "2018-11-02",

    "ACVOL_1": 65276,

    "PCTCHNG": 0.25,

    "BID_NET_CH": 0.0028,

    "BID_TICK_1": "⇧",

    "MID_PRICE": 1.1437,

    "MID_NET_CH": 0.0028,

    "NUM_BIDS": 65276,

    "ACT_TP_1": "B⇧",

    "CTBTR_1": "RBS         ",

    "CTB_LOC1": "LON",

    "CTB_PAGE1": "RBSL",

    "QUOTIM": "09:26:11",

    "QUOTE_DATE": "2018-11-02",

    "QUOTIM_MS": 33971438,

    "BIDPCTCHNG": 0.25,

    "DSPLY_NAME": "RBS          LON",

    "OFFCL_CODE": "RBSL        ",

    "BCKGRNDPAG": "RBSL",

    "ACT_TP_2": "B⇩",

    "ACT_TP_3": "B⇧",

    "DLG_CODE1": "RBSL  ",

    "VALUE_TS2": "09:26:10",

    "VALUE_TS3": "09:26:10",

    "EURO_BNC": 0.0029

}

}

Receive Update Message on session1: {

"ID": 2,

"Type": "Update",

"UpdateType": "Unspecified",

"DoNotConflate": true,

"Key": {

    "Service": "ELEKTRON_DD",

    "Name": "EUR="

},

"SeqNumber": 58014,

"Fields": {

    "EURO_NETCH": 0.0029

}

}