Skip to content

Commit 0a15f51

Browse files
authored
Merge pull request #72 from SaxoBank/ahen/update-wss-url
replaced with new cloud streaming address
2 parents d9c5a22 + 9456627 commit 0a15f51

File tree

11 files changed

+95
-56
lines changed

11 files changed

+95
-56
lines changed

assets/js/boilerplate.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ function demonstrationHelper(settings) {
3232
"redirectUrl": window.location.protocol + "//" + window.location.host + "/openapi-samples-js/assets/html/redirect.html",
3333
"apiHost": "gateway.saxobank.com",
3434
"apiPath": "/sim/openapi", // SIM - Change to "/openapi" when using a Live token
35-
"streamerUrl": "wss://streaming.saxobank.com/sim/openapi/streamingws/connect",
35+
"websocketConnectUrl": "wss://sim-streaming.saxobank.com/sim/oapi/streaming/ws/connect",
36+
"websocketReauthUrl": "https://sim-streaming.saxobank.com/sim/oapi/streaming/ws/authorize",
3637
// App management: https://www.developer.saxo/openapi/appmanagement#/
3738
"appKey": "1a6eb56ced7c4e04b1467e7e9be9bff7" // This is the OAuth2 client_id - no need to create your own app, unless you want to use a different redirect URL
3839
// "appKey": "7194692c30db42efb2c675c6c0fb2a67" // This app is on Legacy AssetTypes, the default before November 2021 - more info: https://saxobank.github.io/openapi-samples-js/instruments/extended-assettypes/
@@ -46,7 +47,8 @@ function demonstrationHelper(settings) {
4647
"redirectUrl": window.location.protocol + "//" + window.location.host + "/openapi-samples-js/assets/html/redirect.html",
4748
"apiHost": "gateway.saxobank.com",
4849
"apiPath": "/openapi",
49-
"streamerUrl": "wss://streaming.saxobank.com/openapi/streamingws/connect",
50+
"websocketConnectUrl": "wss://live-streaming.saxobank.com/oapi/streaming/ws/connect",
51+
"websocketReauthUrl": "https://live-streaming.saxobank.com/oapi/streaming/ws/authorize",
5052
"appKey": "4995383fd4b344e588eb784a7c666835" // This is the OAuth2 client_id - no need to create your own app, unless you want to use a different redirect URL
5153
// "appKey": "ae84ff08844e40d9a7e546bb1c4bdeb7" // This app is on Legacy AssetTypes, the default before November 2021 - more info: https://saxobank.github.io/openapi-samples-js/instruments/extended-assettypes/
5254
};
@@ -57,7 +59,8 @@ function demonstrationHelper(settings) {
5759
"redirectUrl": window.location.protocol + "//" + window.location.host + "/openapi-samples-js/assets/html/redirect.html",
5860
"apiHost": "stgo-tst231.cf.saxo",
5961
"apiPath": "/openapi",
60-
"streamerUrl": "wss://stgo-tst231.cf.saxo/openapi/streamingws/connect", // On staging this is wss://blue.openapi.sys.dom/openapi/streamingws/connect
62+
"websocketConnectUrl": "wss://stgo-tst231.cf.saxo/oapi/streaming/ws/connect", // On staging this is wss://blue.openapi.sys.dom/oapi/streaming/ws/connect
63+
"websocketReauthUrl": "https://stgo-tst231.cf.saxo/oapi/streaming/ws/authorize",
6164
"appKey": "9f07eb9eaf5447469509a03260830990" // This is the OAuth2 client_id - no need to create your own app, unless you want to use a different redirect URL
6265
// "appKey": "91250b8fdceb4713b0bb54b0f0eeae56" // This app is on Legacy AssetTypes, the default before November 2021 - more info: https://saxobank.github.io/openapi-samples-js/instruments/extended-assettypes/
6366
// "appKey": "8ef6e513003e46618d501eec0e213221" // This app has no trading rights - use this to test how it behaves when ordering
@@ -69,7 +72,8 @@ function demonstrationHelper(settings) {
6972
"redirectUrl": window.location.protocol + "//" + window.location.host + "/openapi-samples-js/assets/html/redirect.html",
7073
"apiHost": "stgo-tst211.cf.saxo",
7174
"apiPath": "/openapi",
72-
"streamerUrl": "wss://stgo-tst211.cf.saxo/openapi/streamingws/connect", // On staging this is wss://blue.openapi.sys.dom/openapi/streamingws/connect
75+
"websocketConnectUrl": "wss://stgo-tst211.cf.saxo/oapi/streaming/ws/connect", // On staging this is wss://blue.openapi.sys.dom/oapi/streaming/ws/connect
76+
"websocketReauthUrl": "https://stgo-tst211.cf.saxo/oapi/streaming/ws/authorize",
7377
"appKey": "31eba2b4020c4185a93372a434373cb7" // This is the OAuth2 client_id - no need to create your own app, unless you want to use a different redirect URL
7478
// "appKey": "1c66f4c529ec49cab9303371636fe3d8" // This app is on Legacy AssetTypes, the default before November 2021 - more info: https://saxobank.github.io/openapi-samples-js/instruments/extended-assettypes/
7579
// "appKey": "2c6e16c31a5b404190bc2c90b3bc75bc" // This app has no trading rights - use this to test how it behaves when ordering
@@ -928,7 +932,7 @@ function demonstrationHelper(settings) {
928932
function setupDemo() {
929933
const config = getConfig();
930934
const apiUrl = "https://" + config.apiHost + config.apiPath;
931-
const streamerUrl = config.streamerUrl;
935+
const websocketConnectUrl = config.websocketConnectUrl;
932936
const authUrl = config.authUrl;
933937
mirrorConsoleLog();
934938
mirrorConsoleError();
@@ -950,7 +954,7 @@ function demonstrationHelper(settings) {
950954
return Object.freeze({
951955
apiUrl,
952956
authUrl,
953-
streamerUrl,
957+
websocketConnectUrl,
954958
user,
955959
displayVersion,
956960
displaySourceCode,

sample-apps/realtime-quotes/pricesubscriptionhelper.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,13 @@ function priceSubscriptionHelper(demo) {
4949
* @return {void}
5050
*/
5151
function createConnection() {
52-
const streamerUrl = demo.streamerUrl + "?authorization=Bearer " + encodeURIComponent(bearerToken) + "&contextId=" + encodeURIComponent(contextId);
52+
const websocketConnectUrl = demo.websocketConnectUrl + "?authorization=Bearer " + encodeURIComponent(bearerToken) + "&contextId=" + encodeURIComponent(contextId);
5353
if (!isWebSocketsSupportedByBrowser()) {
5454
console.error("This browser doesn't support WebSockets.");
5555
throw "This browser doesn't support WebSockets.";
5656
}
5757
try {
58-
connection = new window.WebSocket(streamerUrl);
58+
connection = new window.WebSocket(websocketConnectUrl);
5959
connection.binaryType = "arraybuffer";
6060
console.log("Connection created with binaryType '" + connection.binaryType + "'. ReadyState: " + connection.readyState + ".");
6161
// Documentation on readyState: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
@@ -675,7 +675,7 @@ function priceSubscriptionHelper(demo) {
675675
function extendSubscription(accessToken) {
676676
bearerToken = accessToken;
677677
if (connection !== null) {
678-
fetch(demo.apiUrl + "/streamingws/authorize?contextid=" + encodeURIComponent(contextId), getFetchBody("PUT")).then(function (response) {
678+
fetch(demo.apiUrl + "/streaming/ws/authorize?contextid=" + encodeURIComponent(contextId), getFetchBody("PUT")).then(function (response) {
679679
if (response.ok) {
680680
console.log("Websocket subscription extended.");
681681
} else {

websockets/README.md

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# <a name="documentation"></a>Client-side Samples for Websocket feeds
22

3-
This document describes how a client application can subscribe to Saxo Bank's Event Notification Service (ENS).
3+
This document describes how a client application can subscribe to Saxo Bank's Event Notification
4+
Service (ENS).
45

56
Examples on
67
- [Order Events Monitoring (ENS)](order-events-monitoring)
@@ -36,9 +37,12 @@ Native (plain) web sockets are used. Examples in JavaScript.
3637

3738
Prerequisites:
3839

39-
- An access token retrieved using the OAuth2 Authentication flow, as described in the [Saxo documentation](https://www.developer.saxo/openapi/learn/security).
40+
- An access token retrieved using the OAuth2 Authentication flow, as described in the
41+
[Saxo documentation](https://www.developer.saxo/openapi/learn/security).
4042

41-
For this example we use the simulation (sandbox/SIM) environment, with predefined test users and passwords. A user can be created on [Saxo's Developer Portal](https://www.developer.saxo/accounts/sim/signup) for testing.
43+
For this example we use the simulation (sandbox/SIM) environment, with predefined test users and
44+
passwords. A user can be created on
45+
[Saxo's Developer Portal](https://www.developer.saxo/accounts/sim/signup) for testing.
4246

4347
### <a name="realtime1"></a>Step 1: Connect to the feed
4448

@@ -49,16 +53,20 @@ The following code creates and starts a connection:
4953
```javascript
5054
const accessToken = " // paste access token here
5155
const contextId = encodeURIComponent("MyApp" + Date.now());
52-
const streamerUrl = "wss://streaming.saxobank.com/sim/openapi/streamingws/connect?authorization=" + encodeURIComponent("BEARER " + accessToken) + "&contextId=" + contextId;
53-
const connection = new WebSocket(streamerUrl);
56+
const websocketConnectUrl = "wss://sim-streaming.saxobank.com/sim/oapi/streaming/ws/connect?authorization=" + encodeURIComponent("BEARER " + accessToken) + "&contextId=" + contextId;
57+
const connection = new WebSocket(websocketConnectUrl);
5458
console.log("Connection created. Status: " + connection.readyState);
5559
```
5660

5761
**accessToken** – The bearer token, also known as the access token, as provided by the Saxo SSO.
5862

59-
**contextId** - A client-generated unique identifier for the connection. May be up to 50 characters allowing (a-z, A-Z, -, and _). A client application might have multiple connections, identified by different contextIds, but, as you will learn later in this document, one is usually enough per user, as multiple subscriptions can target the same connection.
63+
**contextId** - A client-generated unique identifier for the connection. May be up to 50 characters
64+
allowing (a-z, A-Z, -, and _). A client application might have multiple connections, identified by
65+
different contextIds, but, as you will learn later in this document, one is usually enough per user,
66+
as multiple subscriptions can target the same connection.
6067

61-
More info about the setup at Saxo: <https://www.developer.saxo/openapi/learn/plain-websocket-streaming>.
68+
More info about the setup at Saxo:
69+
<https://www.developer.saxo/openapi/learn/plain-websocket-streaming>.
6270

6371
### <a name="realtime2"></a>Step 2: Handle connection events
6472

@@ -88,7 +96,9 @@ The following code configures the events:
8896

8997
### <a name="realtime3"></a>Step 3: Subscribe to updates
9098

91-
An 'empty' streaming websocket connection is now configured. In order to subscribe to events to be sent on this connection, you need to create a subscription with a POST request to Saxo's OpenAPI. This is an example to subscribe to order events:
99+
An 'empty' streaming websocket connection is now configured. In order to subscribe to events to be
100+
sent on this connection, you need to create a subscription with a POST request to Saxo's OpenAPI.
101+
This is an example to subscribe to order events:
92102

93103
```javascript
94104
const data = {
@@ -122,21 +132,28 @@ An 'empty' streaming websocket connection is now configured. In order to subscri
122132
});
123133
```
124134

125-
**contextId** – The client-generated unique identifier for the connection (so the server can determine the target connection)\
126-
**referenceId** – The client-generated unique reference for the subscription; can be used to identify incoming messages as every event has a referenceId; can be used to do further actions on the subscription, ie. delete it - system event referenceIds are prefixed by an underscore, so better not start with an underscore \
135+
**contextId** – The client-generated unique identifier for the connection (so the server can
136+
determine the target connection)\
137+
**referenceId** – The client-generated unique reference for the subscription; can be used to
138+
identify incoming messages as every event has a referenceId; can be used to do further actions on
139+
the subscription, ie. delete it - system event referenceIds are prefixed by an underscore, so better
140+
not start with an underscore \
127141
**clientKey** – The key identifying the customer\
128142
**accountKey** – The key identifying the account\
129143
**accessToken** – The Bearer token
130144

131145
That’s it. The application is now ready to receive order update messages.
132146

133-
More info about this endpoint: <https://www.developer.saxo/openapi/referencedocs/service?apiVersion=v1&serviceGroup=ens&service=client%20activities>. There you'll read about setting up a refresh rate and how to get (older) snapshot data.
147+
More info about this endpoint:
148+
<https://www.developer.saxo/openapi/referencedocs/service?apiVersion=v1&serviceGroup=ens&service=client%20activities>.
149+
There you'll read about setting up a refresh rate and how to get (older) snapshot data.
134150

135151
### <a name="realtime4"></a>Step 4: Handling events
136152

137153
#### Receiving order events
138154

139-
The order events are published when there is a change in portfolio positions, orders or cash balances.
155+
The order events are published when there is a change in portfolio positions, orders or cash
156+
balances.
140157

141158
As described above, events are received in the onmessage handler:
142159

@@ -259,16 +276,21 @@ As described above, events are received in the onmessage handler:
259276
};
260277
```
261278

262-
The message format is described here: <https://www.developer.saxo/openapi/learn/plain-websocket-streaming#PlainWebSocketStreaming-Receivingmessages>.
279+
The message format is described here:
280+
<https://www.developer.saxo/openapi/learn/plain-websocket-streaming#PlainWebSocketStreaming-Receivingmessages>
281+
.
263282

264283
### <a name="realtime5"></a>Step 5: Extend the subscription before the token expires
265284

266-
The streaming connection will stop when the client disconnects or at the end of the token's expiry. When the client application has refreshed the token using Saxo's standard OAuth refresh flow, any existing streaming connections should be updated with the same token to prevent interruption of the service.
285+
The streaming connection will stop when the client disconnects or at the end of the token's expiry.
286+
When the client application has refreshed the token using Saxo's standard OAuth refresh flow, any
287+
existing streaming connections should be updated with the same token to prevent interruption of the
288+
service.
267289

268290
Extend the subscription using this code:
269291

270292
```javascript
271-
fetch("https://gateway.saxobank.com/sim/openapi/streamingws/authorize?contextid=" + contextId, {
293+
fetch("https://sim-streaming.saxobank.com/sim/oapi/streaming/ws/authorize?contextid=" + contextId, {
272294
"method": "PUT",
273295
"headers": {
274296
"Content-Type": "application/json",
@@ -277,14 +299,18 @@ Extend the subscription using this code:
277299
});
278300
```
279301

280-
**contextId** – The identifyer of the connection (so the server can determine the target connection)\
302+
**contextId** – The identifyer of the connection (so the server can determine the target
303+
connection)\
281304
**accessToken** – The (new) Bearer token
282305

283306
### <a name="realtime6"></a>Step 6: Description of the data
284307

285-
Besides the order events the server sends the following control messages: heartbeats (referenceId: \_heartbeat), disconnect events (\_disconnect) and data-clear-events (\_resetsubscriptions).
308+
Besides the order events the server sends the following control messages: heartbeats (referenceId:
309+
\_heartbeat), disconnect events (\_disconnect) and data-clear-events (\_resetsubscriptions).
286310

287-
More info: <https://www.developer.saxo/openapi/learn/plain-websocket-streaming#PlainWebSocketStreaming-Controlmessages>.
311+
More info:
312+
<https://www.developer.saxo/openapi/learn/plain-websocket-streaming#PlainWebSocketStreaming-Controlmessages>
313+
.
288314

289315
#### Order-object
290316

@@ -329,10 +355,15 @@ An order object is structured as following:
329355
### <a name="realtime7"></a>Adding a netpositions subscription
330356

331357
Next, we need to create a netpositions subscripition, which will provide us with:
332-
1. A snapshot of the client's current positions, which includes *all* data for each netposition. This is similar to sending a GET request to the `/netpositions/me` endpoint.
333-
2. Delta updates whenever individual datapoints for each position change (think: current P&L, conversion rate for instruments in currencies different from the client's account currency, etc).
358+
1. A snapshot of the client's current positions, which includes *all* data for each netposition.
359+
This is similar to sending a GET request to the `/netpositions/me` endpoint.
360+
2. Delta updates whenever individual datapoints for each position change (think: current P&L,
361+
conversion rate for instruments in currencies different from the client's account currency, etc).
334362

335-
The below code is very similar to the code in step 3. This new subscription will be streaming updates on the **same** websocket connection. Note that the `AccountKey` field is optional: if it is *not* provided, netpositions for ALL of the client accounts will be streamed (this is likely what you want if you are looking to provide a 'complete overview' in your UI).
363+
The below code is very similar to the code in step 3. This new subscription will be streaming
364+
updates on the **same** websocket connection. Note that the `AccountKey` field is optional: if it is
365+
*not* provided, netpositions for ALL of the client accounts will be streamed (this is likely what
366+
you want if you are looking to provide a 'complete overview' in your UI).
336367

337368
```javascript
338369
const data = {
@@ -354,7 +385,10 @@ The below code is very similar to the code in step 3. This new subscription will
354385
});
355386
```
356387

357-
The response of the POST request includes the snapshot, with "full" details on the current state of the client's netpositions (not shown here to keep this short). Delta messages only include fields that actually change, which means a real-time representation of the client's portfolio can be created by combining these:
388+
The response of the POST request includes the snapshot, with "full" details on the current state of
389+
the client's netpositions (not shown here to keep this short). Delta messages only include fields
390+
that actually change, which means a real-time representation of the client's portfolio can be
391+
created by combining these:
358392

359393
```javascript
360394
"Data": [{
@@ -374,7 +408,8 @@ The response of the POST request includes the snapshot, with "full" details on t
374408
}]
375409
```
376410

377-
Note the `ConversionRateCurrent` field, which can be used to convert instrument P&L to client account currency P&L (in this case for a JPY-denominated FX position on a USD account).
411+
Note the `ConversionRateCurrent` field, which can be used to convert instrument P&L to client
412+
account currency P&L (in this case for a JPY-denominated FX position on a USD account).
378413

379414
### <a name="realtime8"></a>Whats next: things to keep in mind
380415

websockets/corporateaction-events-monitoring/demo.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
function createConnection() {
4848
const accessToken = document.getElementById("idBearerToken").value;
4949
const contextId = encodeURIComponent(document.getElementById("idContextId").value);
50-
const streamerUrl = demo.streamerUrl + "?authorization=" + encodeURIComponent("BEARER " + accessToken) + "&contextId=" + contextId;
50+
const websocketConnectUrl = demo.websocketConnectUrl + "?authorization=" + encodeURIComponent("BEARER " + accessToken) + "&contextId=" + contextId;
5151
if (!isWebSocketsSupportedByBrowser()) {
5252
console.error("This browser doesn't support WebSockets.");
5353
throw "This browser doesn't support WebSockets.";
@@ -57,7 +57,7 @@
5757
throw "Invalid characters in Context ID.";
5858
}
5959
try {
60-
connection = new window.WebSocket(streamerUrl);
60+
connection = new window.WebSocket(websocketConnectUrl);
6161
connection.binaryType = "arraybuffer";
6262
console.log("Connection created with binaryType '" + connection.binaryType + "'. ReadyState: " + connection.readyState + ".");
6363
// Documentation on readyState: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
@@ -462,7 +462,7 @@
462462
// Example: https://saxobank.github.io/openapi-samples-js/authentication/oauth2-implicit-flow/
463463
const token = document.getElementById("idBearerToken").value;
464464
fetch(
465-
demo.apiUrl + "/streamingws/authorize?contextid=" + encodeURIComponent(document.getElementById("idContextId").value),
465+
demo.websocketReauthUrl + "?contextid=" + encodeURIComponent(document.getElementById("idContextId").value),
466466
{
467467
"method": "PUT",
468468
"headers": {

0 commit comments

Comments
 (0)