@tastytrade/api 3.1.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/launch.json +29 -0
- package/CHANGELOG.md +26 -0
- package/CODEOWNERS +1 -0
- package/README.md +4 -2
- package/dist/account-streamer.d.ts +7 -6
- package/dist/account-streamer.d.ts.map +1 -0
- package/dist/account-streamer.js +145 -228
- package/dist/account-streamer.js.map +1 -0
- package/dist/market-data-streamer.d.ts +7 -5
- package/dist/market-data-streamer.d.ts.map +1 -0
- package/dist/market-data-streamer.js +139 -172
- package/dist/market-data-streamer.js.map +1 -0
- package/dist/models/tastytrade-session.d.ts +1 -0
- package/dist/models/tastytrade-session.d.ts.map +1 -0
- package/dist/models/tastytrade-session.js +10 -20
- package/dist/models/tastytrade-session.js.map +1 -0
- package/dist/services/account-status-service.d.ts +2 -1
- package/dist/services/account-status-service.d.ts.map +1 -0
- package/dist/services/account-status-service.js +11 -60
- package/dist/services/account-status-service.js.map +1 -0
- package/dist/services/accounts-and-customers-service.d.ts +2 -1
- package/dist/services/accounts-and-customers-service.d.ts.map +1 -0
- package/dist/services/accounts-and-customers-service.js +29 -112
- package/dist/services/accounts-and-customers-service.js.map +1 -0
- package/dist/services/balances-and-positions-service.d.ts +2 -1
- package/dist/services/balances-and-positions-service.d.ts.map +1 -0
- package/dist/services/balances-and-positions-service.js +22 -88
- package/dist/services/balances-and-positions-service.js.map +1 -0
- package/dist/services/instruments-service.d.ts +2 -1
- package/dist/services/instruments-service.d.ts.map +1 -0
- package/dist/services/instruments-service.js +130 -365
- package/dist/services/instruments-service.js.map +1 -0
- package/dist/services/margin-requirements-service.d.ts +2 -1
- package/dist/services/margin-requirements-service.d.ts.map +1 -0
- package/dist/services/margin-requirements-service.js +16 -73
- package/dist/services/margin-requirements-service.js.map +1 -0
- package/dist/services/market-metrics-service.d.ts +2 -1
- package/dist/services/market-metrics-service.d.ts.map +1 -0
- package/dist/services/market-metrics-service.js +21 -88
- package/dist/services/market-metrics-service.js.map +1 -0
- package/dist/services/net-liquidating-value-history-service.d.ts +2 -1
- package/dist/services/net-liquidating-value-history-service.d.ts.map +1 -0
- package/dist/services/net-liquidating-value-history-service.js +16 -74
- package/dist/services/net-liquidating-value-history-service.js.map +1 -0
- package/dist/services/orders-service.d.ts +2 -1
- package/dist/services/orders-service.d.ts.map +1 -0
- package/dist/services/orders-service.js +76 -231
- package/dist/services/orders-service.js.map +1 -0
- package/dist/services/risk-parameters-service.d.ts +2 -1
- package/dist/services/risk-parameters-service.d.ts.map +1 -0
- package/dist/services/risk-parameters-service.js +16 -73
- package/dist/services/risk-parameters-service.js.map +1 -0
- package/dist/services/session-service.d.ts +2 -1
- package/dist/services/session-service.d.ts.map +1 -0
- package/dist/services/session-service.js +30 -110
- package/dist/services/session-service.js.map +1 -0
- package/dist/services/symbol-search-service.d.ts +2 -1
- package/dist/services/symbol-search-service.d.ts.map +1 -0
- package/dist/services/symbol-search-service.js +11 -60
- package/dist/services/symbol-search-service.js.map +1 -0
- package/dist/services/tastytrade-http-client.d.ts +2 -2
- package/dist/services/tastytrade-http-client.d.ts.map +1 -0
- package/dist/services/tastytrade-http-client.js +51 -134
- package/dist/services/tastytrade-http-client.js.map +1 -0
- package/dist/services/transactions-service.d.ts +2 -1
- package/dist/services/transactions-service.d.ts.map +1 -0
- package/dist/services/transactions-service.js +22 -87
- package/dist/services/transactions-service.js.map +1 -0
- package/dist/services/watchlists-service.d.ts +2 -1
- package/dist/services/watchlists-service.d.ts.map +1 -0
- package/dist/services/watchlists-service.js +51 -165
- package/dist/services/watchlists-service.js.map +1 -0
- package/dist/tastytrade-api.d.ts +20 -19
- package/dist/tastytrade-api.d.ts.map +1 -0
- package/dist/tastytrade-api.js +41 -77
- package/dist/tastytrade-api.js.map +1 -0
- package/dist/utils/constants.d.ts +1 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/constants.js +2 -4
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/json-util.d.ts +4 -3
- package/dist/utils/json-util.d.ts.map +1 -0
- package/dist/utils/json-util.js +14 -25
- package/dist/utils/json-util.js.map +1 -0
- package/dist/utils/response-util.d.ts +1 -0
- package/dist/utils/response-util.d.ts.map +1 -0
- package/dist/utils/response-util.js +7 -12
- package/dist/utils/response-util.js.map +1 -0
- package/lib/account-streamer.ts +4 -4
- package/lib/market-data-streamer.ts +5 -1
- package/lib/services/account-status-service.ts +2 -2
- package/lib/services/accounts-and-customers-service.ts +2 -2
- package/lib/services/balances-and-positions-service.ts +2 -2
- package/lib/services/instruments-service.ts +2 -2
- package/lib/services/margin-requirements-service.ts +2 -2
- package/lib/services/market-metrics-service.ts +2 -2
- package/lib/services/net-liquidating-value-history-service.ts +2 -2
- package/lib/services/orders-service.ts +2 -2
- package/lib/services/risk-parameters-service.ts +2 -2
- package/lib/services/session-service.ts +2 -2
- package/lib/services/symbol-search-service.ts +2 -2
- package/lib/services/tastytrade-http-client.ts +15 -14
- package/lib/services/transactions-service.ts +2 -2
- package/lib/services/watchlists-service.ts +2 -2
- package/lib/tastytrade-api.ts +19 -19
- package/package.json +14 -9
- package/tsconfig.json +12 -11
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Use IntelliSense to learn about possible attributes.
|
|
3
|
+
// Hover to view descriptions of existing attributes.
|
|
4
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"configurations": [
|
|
7
|
+
{
|
|
8
|
+
"type": "node",
|
|
9
|
+
"request": "launch",
|
|
10
|
+
"name": "Typescript",
|
|
11
|
+
"skipFiles": [
|
|
12
|
+
"<node_internals>/**"
|
|
13
|
+
],
|
|
14
|
+
"runtimeExecutable": "ts-node",
|
|
15
|
+
// "runtimeArgs": ["--nolazy", "-r", "ts-node/register/transpile-only"],
|
|
16
|
+
"args": ["thingy/main.ts"]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"type": "node",
|
|
20
|
+
"request": "launch",
|
|
21
|
+
"name": "Javascript",
|
|
22
|
+
"skipFiles": [
|
|
23
|
+
"<node_internals>/**"
|
|
24
|
+
],
|
|
25
|
+
"runtimeExecutable": "node",
|
|
26
|
+
"args": ["thingy/default.js"]
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# @tastytrade/api
|
|
2
|
+
All notable changes to this project will be documented in this file.
|
|
3
|
+
|
|
4
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
5
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [4.0.0] - 2024-03-12
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Tsconfig library updates [#35](https://github.com/tastytrade/tastytrade-api-js/pull/35)
|
|
14
|
+
- target modern JS modules [#30](https://github.com/tastytrade/tastytrade-api-js/pull/30)
|
|
15
|
+
- Deprecate MarketDataStreamer [#29](https://github.com/tastytrade/tastytrade-api-js/pull/29)
|
|
16
|
+
- Target moden node runtimes [#22](https://github.com/tastytrade/tastytrade-api-js/pull/22)
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- add missing return in getDefaultHeaders [#32](https://github.com/tastytrade/tastytrade-api-js/pull/32)
|
|
21
|
+
- Dont set User-Agent header in browser environment [#28](https://github.com/tastytrade/tastytrade-api-js/pull/28)
|
|
22
|
+
|
|
23
|
+
### Removed
|
|
24
|
+
|
|
25
|
+
- Remove https.Agent in `tastytrade-http-client` [#24](https://github.com/tastytrade/tastytrade-api-js/pull/24)
|
|
26
|
+
- Remove un-needed types dependency [#21](https://github.com/tastytrade/tastytrade-api-js/pull/21)
|
package/CODEOWNERS
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @dmoss18
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ yarn:
|
|
|
11
11
|
```js
|
|
12
12
|
import TastytradeClient from "@tastytrade/api"
|
|
13
13
|
const tastytradeClient = new TastytradeClient(baseUrl, accountStreamerUrl)
|
|
14
|
-
const loginResponse = await tastytradeClient.sessionService.login(usernameOrEmail,
|
|
14
|
+
const loginResponse = await tastytradeClient.sessionService.login(usernameOrEmail, password)
|
|
15
15
|
const accounts = await tastytradeClient.accountsAndCustomersService.getCustomerAccounts()
|
|
16
16
|
const accountPositions = await tastytradeClient.balancesAndPositionsService.getPositionsList(accounts[0].accounts['account-number'])
|
|
17
17
|
```
|
|
@@ -20,7 +20,7 @@ const accountPositions = await tastytradeClient.balancesAndPositionsService.getP
|
|
|
20
20
|
```js
|
|
21
21
|
import TastytradeClient, { MarketDataStreamer, MarketDataSubscriptionType } from "@tastytrade-api"
|
|
22
22
|
const tastytradeClient = new TastytradeClient(baseUrl, accountStreamerUrl)
|
|
23
|
-
await tastytradeClient.sessionService.login(usernameOrEmail,
|
|
23
|
+
await tastytradeClient.sessionService.login(usernameOrEmail, password)
|
|
24
24
|
const tokenResponse = await tastytradeClient.AccountsAndCustomersService.getApiQuoteToken()
|
|
25
25
|
const streamer = new MarketDataStreamer()
|
|
26
26
|
streamer.connect(tokenResponse['dxlink-url'], tokenResponse.token)
|
|
@@ -95,6 +95,8 @@ API_PASSWORD=<your cert password>
|
|
|
95
95
|
API_ACCOUNT_NUMBER=<your cert account number>
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
+
These values should match whatever username/password/account you set up in the tastytrade sandbox environment. Head to developer.tastyworks.com to get that set up.
|
|
99
|
+
|
|
98
100
|
## Running example app
|
|
99
101
|
```sh
|
|
100
102
|
npm run build
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import type { JsonValue } from './utils/json-util';
|
|
2
|
-
import { JsonBuilder } from './utils/json-util';
|
|
3
|
-
import TastytradeSession from './models/tastytrade-session';
|
|
1
|
+
import type { JsonValue } from './utils/json-util.js';
|
|
2
|
+
import { JsonBuilder } from './utils/json-util.js';
|
|
3
|
+
import TastytradeSession from './models/tastytrade-session.js';
|
|
4
4
|
export declare enum STREAMER_STATE {
|
|
5
5
|
Open = 0,
|
|
6
6
|
Closed = 1,
|
|
7
7
|
Error = 2
|
|
8
8
|
}
|
|
9
|
-
export
|
|
10
|
-
export
|
|
11
|
-
export
|
|
9
|
+
export type Disposer = () => void;
|
|
10
|
+
export type StreamerStateObserver = (streamerState: STREAMER_STATE) => void;
|
|
11
|
+
export type StreamerMessageObserver = (json: object) => void;
|
|
12
12
|
export declare class AccountStreamer {
|
|
13
13
|
private readonly url;
|
|
14
14
|
private readonly session;
|
|
@@ -90,3 +90,4 @@ export declare class AccountStreamer {
|
|
|
90
90
|
addMessageObserver(observer: StreamerMessageObserver): Disposer;
|
|
91
91
|
private readonly handleOneMessage;
|
|
92
92
|
}
|
|
93
|
+
//# sourceMappingURL=account-streamer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-streamer.d.ts","sourceRoot":"","sources":["../lib/account-streamer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAW,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAClD,OAAO,iBAAiB,MAAM,gCAAgC,CAAA;AAG9D,oBAAY,cAAc;IACxB,IAAI,IAAI;IACR,MAAM,IAAI;IACV,KAAK,IAAI;CACV;AAeD,MAAM,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAA;AAEjC,MAAM,MAAM,qBAAqB,GAAG,CAAC,aAAa,EAAE,cAAc,KAAK,IAAI,CAAA;AAE3E,MAAM,MAAM,uBAAuB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;AAa5D,qBAAa,eAAe;IA8Bd,OAAO,CAAC,QAAQ,CAAC,GAAG;IAAU,OAAO,CAAC,QAAQ,CAAC,OAAO;IA7BlE,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,YAAY,CAA2C;IAC/D,OAAO,CAAC,WAAW,CAAwC;IAC3D,OAAO,CAAC,cAAc,CAAY;IAClC,OAAO,CAAC,MAAM,CAAe;IAE7B,OAAO,CAAC,gBAAgB,CAAuC;IAE/D,cAAc,EAAE,GAAG,CAAO;IAC1B,cAAc,EAAE,GAAG,CAAO;IAC1B,OAAO,CAAC,cAAc,CAAwC;IAE9D,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA8B;IAErE,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAgC;IAEzE,OAAO,CAAC,YAAY,CAAgC;IAEpD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAGnB;IAEb,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;IAEjC;;;OAGG;gBAC0B,GAAG,EAAE,MAAM,EAAmB,OAAO,EAAE,iBAAiB;IAErF,IAAI,aAAa,IAAI,cAAc,CAElC;IAED,IAAI,aAAa,CAAC,aAAa,EAAE,cAAc,EAM9C;IAED,OAAO,KAAK,SAAS,GAEpB;IAED;;;;OAIG;IACH,wBAAwB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,QAAQ;IAQnE,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAyB/B,IAAI;IAIJ,OAAO,CAAC,QAAQ;IAsBhB,QAAQ,CAAC,aAAa,aAGrB;IAED,OAAO,CAAC,sBAAsB;IAc9B,IAAI,oBAAoB,YAEvB;IAED,OAAO,CAAC,oBAAoB;IAc5B,OAAO,CAAC,qBAAqB;IAI7B;;;;;OAKG;IACH,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,mBAAmB,UAAO,GAAG,MAAM;IA0B3D;;;;;OAKG;IACI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,GAAG,MAAM;IAS7D;;;;OAIG;IACI,eAAe,CAAC,cAAc,EAAE,MAAM;IAQ7C;;;;OAIG;IACU,mBAAmB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAc3E,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAa1B;IAED,OAAO,CAAC,QAAQ,CAAC,WAAW,CAS3B;IAED,OAAO,CAAC,QAAQ,CAAC,WAAW,CAgB3B;IAED,OAAO,CAAC,QAAQ,CAAC,aAAa,CAW7B;IAED,kBAAkB,CAAC,QAAQ,EAAE,uBAAuB,GAAG,QAAQ;IAQ/D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CA0BhC;CACF"}
|
package/dist/account-streamer.js
CHANGED
|
@@ -1,55 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (_) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
-
};
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.AccountStreamer = exports.STREAMER_STATE = void 0;
|
|
43
|
-
var isomorphic_ws_1 = __importDefault(require("isomorphic-ws"));
|
|
44
|
-
var lodash_1 = __importDefault(require("lodash"));
|
|
45
|
-
var json_util_1 = require("./utils/json-util");
|
|
46
|
-
var constants_1 = require("./utils/constants");
|
|
47
|
-
var STREAMER_STATE;
|
|
1
|
+
import WebSocket from 'isomorphic-ws';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
import { JsonBuilder } from './utils/json-util.js';
|
|
4
|
+
import TastytradeSession from './models/tastytrade-session.js';
|
|
5
|
+
import { MinTlsVersion } from './utils/constants.js';
|
|
6
|
+
export var STREAMER_STATE;
|
|
48
7
|
(function (STREAMER_STATE) {
|
|
49
8
|
STREAMER_STATE[STREAMER_STATE["Open"] = 0] = "Open";
|
|
50
9
|
STREAMER_STATE[STREAMER_STATE["Closed"] = 1] = "Closed";
|
|
51
10
|
STREAMER_STATE[STREAMER_STATE["Error"] = 2] = "Error";
|
|
52
|
-
})(STREAMER_STATE
|
|
11
|
+
})(STREAMER_STATE || (STREAMER_STATE = {}));
|
|
53
12
|
var MessageAction;
|
|
54
13
|
(function (MessageAction) {
|
|
55
14
|
MessageAction["ACCOUNT_SUBSCRIBE"] = "account-subscribe";
|
|
@@ -59,23 +18,22 @@ var MessageAction;
|
|
|
59
18
|
MessageAction["QUOTE_ALERTS_SUBSCRIBE"] = "quote-alerts-subscribe";
|
|
60
19
|
MessageAction["USER_MESSAGE_SUBSCRIBE"] = "user-message-subscribe";
|
|
61
20
|
})(MessageAction || (MessageAction = {}));
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
21
|
+
const HEARTBEAT_INTERVAL = 20000; // 20 seconds
|
|
22
|
+
const SOURCE = 'tastytrade-api-js-sdk';
|
|
23
|
+
const REQUEST_ID = 'request-id';
|
|
65
24
|
function removeElement(array, element) {
|
|
66
|
-
|
|
25
|
+
const index = array.indexOf(element);
|
|
67
26
|
if (index < 0) {
|
|
68
27
|
return;
|
|
69
28
|
}
|
|
70
29
|
array.splice(index, 1);
|
|
71
30
|
}
|
|
72
|
-
|
|
31
|
+
export class AccountStreamer {
|
|
73
32
|
/**
|
|
74
33
|
*
|
|
75
34
|
* @param url Url of the account streamer service
|
|
76
35
|
*/
|
|
77
|
-
|
|
78
|
-
var _this = this;
|
|
36
|
+
constructor(url, session) {
|
|
79
37
|
this.url = url;
|
|
80
38
|
this.session = session;
|
|
81
39
|
this.websocket = null;
|
|
@@ -92,70 +50,69 @@ var AccountStreamer = /** @class */ (function () {
|
|
|
92
50
|
this.startPromise = null;
|
|
93
51
|
this.requestPromises = new Map();
|
|
94
52
|
this.logger = console;
|
|
95
|
-
this.sendHeartbeat =
|
|
96
|
-
|
|
97
|
-
|
|
53
|
+
this.sendHeartbeat = () => {
|
|
54
|
+
this.clearHeartbeatTimerId();
|
|
55
|
+
this.send(new JsonBuilder({ action: MessageAction.HEARTBEAT }));
|
|
98
56
|
};
|
|
99
|
-
this.handleOpen =
|
|
100
|
-
if (
|
|
57
|
+
this.handleOpen = (event) => {
|
|
58
|
+
if (this.startResolve === null) {
|
|
101
59
|
return;
|
|
102
60
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
61
|
+
this.logger.info('AccountStreamer opened', event);
|
|
62
|
+
this.startResolve(true);
|
|
63
|
+
this.startResolve = this.startReject = null;
|
|
64
|
+
this.streamerState = STREAMER_STATE.Open;
|
|
65
|
+
this.sendQueuedMessages();
|
|
66
|
+
this.scheduleHeartbeatTimer();
|
|
109
67
|
};
|
|
110
|
-
this.handleClose =
|
|
111
|
-
|
|
112
|
-
if (
|
|
68
|
+
this.handleClose = (event) => {
|
|
69
|
+
this.logger.info('AccountStreamer closed', event);
|
|
70
|
+
if (this.websocket === null) {
|
|
113
71
|
return;
|
|
114
72
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
73
|
+
this.lastCloseEvent = event;
|
|
74
|
+
this.streamerState = STREAMER_STATE.Closed;
|
|
75
|
+
this.teardown();
|
|
118
76
|
};
|
|
119
|
-
this.handleError =
|
|
120
|
-
if (
|
|
77
|
+
this.handleError = (event) => {
|
|
78
|
+
if (this.websocket === null) {
|
|
121
79
|
return;
|
|
122
80
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
|
|
81
|
+
this.logger.warn('AccountStreamer error', event);
|
|
82
|
+
this.lastErrorEvent = event;
|
|
83
|
+
this.streamerState = STREAMER_STATE.Error;
|
|
84
|
+
if (this.startReject !== null) {
|
|
85
|
+
this.startReject(new Error('Failed to connect'));
|
|
86
|
+
this.startReject = this.startResolve = null;
|
|
129
87
|
}
|
|
130
|
-
|
|
88
|
+
this.teardown();
|
|
131
89
|
};
|
|
132
|
-
this.handleMessage =
|
|
133
|
-
|
|
90
|
+
this.handleMessage = (event) => {
|
|
91
|
+
const json = JSON.parse(event.data);
|
|
134
92
|
if (json.results !== undefined) {
|
|
135
|
-
|
|
136
|
-
for (
|
|
137
|
-
|
|
138
|
-
_this.handleOneMessage(result);
|
|
93
|
+
const results = json.results;
|
|
94
|
+
for (const result of results) {
|
|
95
|
+
this.handleOneMessage(result);
|
|
139
96
|
}
|
|
140
97
|
}
|
|
141
98
|
else {
|
|
142
|
-
|
|
99
|
+
this.handleOneMessage(json);
|
|
143
100
|
}
|
|
144
101
|
};
|
|
145
|
-
this.handleOneMessage =
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
102
|
+
this.handleOneMessage = (json) => {
|
|
103
|
+
this.logger.info(json);
|
|
104
|
+
const action = json.action;
|
|
105
|
+
this.streamerMessageObservers.forEach(observer => observer(json));
|
|
149
106
|
if (action) {
|
|
150
107
|
if (action === MessageAction.HEARTBEAT) {
|
|
151
108
|
// schedule next heartbeat
|
|
152
|
-
|
|
109
|
+
this.scheduleHeartbeatTimer();
|
|
153
110
|
}
|
|
154
|
-
|
|
111
|
+
const promiseCallbacks = this.requestPromises.get(json[REQUEST_ID]);
|
|
155
112
|
if (promiseCallbacks) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if (
|
|
113
|
+
const [resolve, reject] = promiseCallbacks;
|
|
114
|
+
const status = json.status;
|
|
115
|
+
if (status === 'ok') {
|
|
159
116
|
resolve(json.action);
|
|
160
117
|
}
|
|
161
118
|
else {
|
|
@@ -166,96 +123,69 @@ var AccountStreamer = /** @class */ (function () {
|
|
|
166
123
|
}
|
|
167
124
|
};
|
|
168
125
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
});
|
|
182
|
-
Object.defineProperty(AccountStreamer.prototype, "authToken", {
|
|
183
|
-
get: function () {
|
|
184
|
-
return this.session.authToken;
|
|
185
|
-
},
|
|
186
|
-
enumerable: false,
|
|
187
|
-
configurable: true
|
|
188
|
-
});
|
|
126
|
+
get streamerState() {
|
|
127
|
+
return this._streamerState;
|
|
128
|
+
}
|
|
129
|
+
set streamerState(streamerState) {
|
|
130
|
+
this._streamerState = streamerState;
|
|
131
|
+
this.streamerStateObservers.forEach(observer => {
|
|
132
|
+
observer(streamerState);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
get authToken() {
|
|
136
|
+
return this.session.authToken;
|
|
137
|
+
}
|
|
189
138
|
/**
|
|
190
139
|
* Adds a custom callback that fires when the streamer state changes
|
|
191
140
|
* @param observer
|
|
192
141
|
* @returns
|
|
193
142
|
*/
|
|
194
|
-
|
|
195
|
-
var _this = this;
|
|
143
|
+
addStreamerStateObserver(observer) {
|
|
196
144
|
this.streamerStateObservers.push(observer);
|
|
197
|
-
return
|
|
198
|
-
removeElement(
|
|
145
|
+
return () => {
|
|
146
|
+
removeElement(this.streamerStateObservers, observer);
|
|
199
147
|
};
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
return this.streamerState === STREAMER_STATE.Closed;
|
|
211
|
-
},
|
|
212
|
-
enumerable: false,
|
|
213
|
-
configurable: true
|
|
214
|
-
});
|
|
215
|
-
Object.defineProperty(AccountStreamer.prototype, "isError", {
|
|
216
|
-
get: function () {
|
|
217
|
-
return this.streamerState === STREAMER_STATE.Error;
|
|
218
|
-
},
|
|
219
|
-
enumerable: false,
|
|
220
|
-
configurable: true
|
|
221
|
-
});
|
|
148
|
+
}
|
|
149
|
+
get isOpen() {
|
|
150
|
+
return this.streamerState === STREAMER_STATE.Open;
|
|
151
|
+
}
|
|
152
|
+
get isClosed() {
|
|
153
|
+
return this.streamerState === STREAMER_STATE.Closed;
|
|
154
|
+
}
|
|
155
|
+
get isError() {
|
|
156
|
+
return this.streamerState === STREAMER_STATE.Error;
|
|
157
|
+
}
|
|
222
158
|
/**
|
|
223
159
|
* Entrypoint for beginning a websocket session
|
|
224
160
|
* You must have a valid tastytrade authToken before calling this method
|
|
225
161
|
* @returns Promise that resolves when the "opened" message is received (see handleOpen)
|
|
226
162
|
*/
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
return [2 /*return*/, this.startPromise];
|
|
234
|
-
}
|
|
235
|
-
this.websocket = new isomorphic_ws_1.default(this.url, [], {
|
|
236
|
-
minVersion: constants_1.MinTlsVersion // TLS Config
|
|
237
|
-
});
|
|
238
|
-
websocket = this.websocket;
|
|
239
|
-
this.lastCloseEvent = null;
|
|
240
|
-
this.lastErrorEvent = null;
|
|
241
|
-
websocket.addEventListener('open', this.handleOpen);
|
|
242
|
-
websocket.addEventListener('close', this.handleClose);
|
|
243
|
-
websocket.addEventListener('error', this.handleError);
|
|
244
|
-
websocket.addEventListener('message', this.handleMessage);
|
|
245
|
-
this.logger.info('AccountStreamer - starting');
|
|
246
|
-
this.startPromise = new Promise(function (resolve, reject) {
|
|
247
|
-
_this.startResolve = resolve;
|
|
248
|
-
_this.startReject = reject;
|
|
249
|
-
});
|
|
250
|
-
return [2 /*return*/, this.startPromise];
|
|
251
|
-
});
|
|
163
|
+
async start() {
|
|
164
|
+
if (this.startPromise !== null) {
|
|
165
|
+
return this.startPromise;
|
|
166
|
+
}
|
|
167
|
+
this.websocket = new WebSocket(this.url, [], {
|
|
168
|
+
minVersion: MinTlsVersion // TLS Config
|
|
252
169
|
});
|
|
253
|
-
|
|
254
|
-
|
|
170
|
+
const websocket = this.websocket;
|
|
171
|
+
this.lastCloseEvent = null;
|
|
172
|
+
this.lastErrorEvent = null;
|
|
173
|
+
websocket.addEventListener('open', this.handleOpen);
|
|
174
|
+
websocket.addEventListener('close', this.handleClose);
|
|
175
|
+
websocket.addEventListener('error', this.handleError);
|
|
176
|
+
websocket.addEventListener('message', this.handleMessage);
|
|
177
|
+
this.logger.info('AccountStreamer - starting');
|
|
178
|
+
this.startPromise = new Promise((resolve, reject) => {
|
|
179
|
+
this.startResolve = resolve;
|
|
180
|
+
this.startReject = reject;
|
|
181
|
+
});
|
|
182
|
+
return this.startPromise;
|
|
183
|
+
}
|
|
184
|
+
stop() {
|
|
255
185
|
this.teardown();
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
|
|
186
|
+
}
|
|
187
|
+
teardown() {
|
|
188
|
+
const websocket = this.websocket;
|
|
259
189
|
if (websocket === null) {
|
|
260
190
|
return;
|
|
261
191
|
}
|
|
@@ -269,24 +199,20 @@ var AccountStreamer = /** @class */ (function () {
|
|
|
269
199
|
this.websocket = null;
|
|
270
200
|
this.logger.info('AccountStreamer - teardown');
|
|
271
201
|
this.streamerState = STREAMER_STATE.Closed; // Manually update status for convenience
|
|
272
|
-
}
|
|
273
|
-
|
|
202
|
+
}
|
|
203
|
+
scheduleHeartbeatTimer() {
|
|
274
204
|
if (this.isHeartbeatScheduled) {
|
|
275
205
|
// Heartbeat already scheduled
|
|
276
206
|
return;
|
|
277
207
|
}
|
|
278
208
|
this.logger.info('Scheduling heartbeat with interval: ', HEARTBEAT_INTERVAL);
|
|
279
|
-
|
|
209
|
+
const scheduler = typeof window === 'undefined' ? setTimeout : window.setTimeout;
|
|
280
210
|
this.heartbeatTimerId = scheduler(this.sendHeartbeat, HEARTBEAT_INTERVAL);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
enumerable: false,
|
|
287
|
-
configurable: true
|
|
288
|
-
});
|
|
289
|
-
AccountStreamer.prototype.cancelHeartbeatTimer = function () {
|
|
211
|
+
}
|
|
212
|
+
get isHeartbeatScheduled() {
|
|
213
|
+
return !_.isNil(this.heartbeatTimerId);
|
|
214
|
+
}
|
|
215
|
+
cancelHeartbeatTimer() {
|
|
290
216
|
if (!this.isHeartbeatScheduled) {
|
|
291
217
|
return; // Nothing to cancel
|
|
292
218
|
}
|
|
@@ -297,30 +223,29 @@ var AccountStreamer = /** @class */ (function () {
|
|
|
297
223
|
clearTimeout(this.heartbeatTimerId);
|
|
298
224
|
}
|
|
299
225
|
this.clearHeartbeatTimerId();
|
|
300
|
-
}
|
|
301
|
-
|
|
226
|
+
}
|
|
227
|
+
clearHeartbeatTimerId() {
|
|
302
228
|
this.heartbeatTimerId = null;
|
|
303
|
-
}
|
|
229
|
+
}
|
|
304
230
|
/**
|
|
305
231
|
* Send a message via websocket
|
|
306
232
|
* @param json JsonBuilder
|
|
307
233
|
* @param includeSessionToken Attaches session token to message if true
|
|
308
234
|
* @returns
|
|
309
235
|
*/
|
|
310
|
-
|
|
311
|
-
if (includeSessionToken === void 0) { includeSessionToken = true; }
|
|
236
|
+
send(json, includeSessionToken = true) {
|
|
312
237
|
this.requestCounter += 1;
|
|
313
238
|
json.add(REQUEST_ID, this.requestCounter);
|
|
314
239
|
json.add('source', SOURCE);
|
|
315
240
|
if (includeSessionToken) {
|
|
316
|
-
|
|
241
|
+
const sessionToken = this.authToken;
|
|
317
242
|
if (!sessionToken) {
|
|
318
243
|
throw new Error('sessionToken not set');
|
|
319
244
|
}
|
|
320
245
|
json.add('auth-token', sessionToken);
|
|
321
246
|
}
|
|
322
|
-
|
|
323
|
-
|
|
247
|
+
const message = JSON.stringify(json.json);
|
|
248
|
+
const websocket = this.websocket;
|
|
324
249
|
if (websocket === null) {
|
|
325
250
|
// Queue up and send on open
|
|
326
251
|
this.queued.push(message);
|
|
@@ -329,71 +254,63 @@ var AccountStreamer = /** @class */ (function () {
|
|
|
329
254
|
websocket.send(message);
|
|
330
255
|
}
|
|
331
256
|
return this.requestCounter;
|
|
332
|
-
}
|
|
257
|
+
}
|
|
333
258
|
/**
|
|
334
259
|
* Used by other methods to send a specific `action` message
|
|
335
260
|
* @param action
|
|
336
261
|
* @param value
|
|
337
262
|
* @returns
|
|
338
263
|
*/
|
|
339
|
-
|
|
340
|
-
|
|
264
|
+
subscribeTo(action, value) {
|
|
265
|
+
const json = new JsonBuilder();
|
|
341
266
|
json.add('action', action);
|
|
342
|
-
if (!
|
|
267
|
+
if (!_.isUndefined(value)) {
|
|
343
268
|
json.add('value', value);
|
|
344
269
|
}
|
|
345
270
|
return this.send(json);
|
|
346
|
-
}
|
|
271
|
+
}
|
|
347
272
|
/**
|
|
348
273
|
* Subscribes to all user-level messages for given user external id
|
|
349
274
|
* @param userExternalId "external-id" from login response
|
|
350
275
|
* @returns Promise that resolves when ack is received
|
|
351
276
|
*/
|
|
352
|
-
|
|
277
|
+
subscribeToUser(userExternalId) {
|
|
353
278
|
if (!userExternalId) {
|
|
354
279
|
return;
|
|
355
280
|
}
|
|
356
281
|
this.subscribeTo(MessageAction.USER_MESSAGE_SUBSCRIBE, userExternalId);
|
|
357
|
-
}
|
|
282
|
+
}
|
|
358
283
|
/**
|
|
359
284
|
* Subscribes to all account-level messages for given account numbers
|
|
360
285
|
* @param accountNumbers List of account numbers to subscribe to
|
|
361
286
|
* @returns Promise that resolves when an ack is received
|
|
362
287
|
*/
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
value = accountNumbers.length > 1 ? accountNumbers : accountNumbers[0];
|
|
372
|
-
requestId = this.subscribeTo(MessageAction.CONNECT, value);
|
|
373
|
-
return [2 /*return*/, new Promise(function (resolve, reject) {
|
|
374
|
-
_this.requestPromises.set(requestId, [resolve, reject]);
|
|
375
|
-
})];
|
|
376
|
-
});
|
|
288
|
+
async subscribeToAccounts(accountNumbers) {
|
|
289
|
+
if (accountNumbers.length === 0) {
|
|
290
|
+
return Promise.reject('no account numbers');
|
|
291
|
+
}
|
|
292
|
+
const value = accountNumbers.length > 1 ? accountNumbers : accountNumbers[0];
|
|
293
|
+
const requestId = this.subscribeTo(MessageAction.CONNECT, value);
|
|
294
|
+
return new Promise((resolve, reject) => {
|
|
295
|
+
this.requestPromises.set(requestId, [resolve, reject]);
|
|
377
296
|
});
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
|
|
297
|
+
}
|
|
298
|
+
sendQueuedMessages() {
|
|
299
|
+
const queued = this.queued;
|
|
381
300
|
if (queued.length === 0 || this.websocket === null) {
|
|
382
301
|
return;
|
|
383
302
|
}
|
|
384
|
-
|
|
385
|
-
queued.forEach(
|
|
303
|
+
const websocket = this.websocket;
|
|
304
|
+
queued.forEach(msg => {
|
|
386
305
|
websocket.send(msg);
|
|
387
306
|
});
|
|
388
307
|
this.queued = [];
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
var _this = this;
|
|
308
|
+
}
|
|
309
|
+
addMessageObserver(observer) {
|
|
392
310
|
this.streamerMessageObservers.push(observer);
|
|
393
|
-
return
|
|
394
|
-
removeElement(
|
|
311
|
+
return () => {
|
|
312
|
+
removeElement(this.streamerMessageObservers, observer);
|
|
395
313
|
};
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
exports.AccountStreamer = AccountStreamer;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
//# sourceMappingURL=account-streamer.js.map
|