ctrader-x 0.1.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.
Files changed (147) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +177 -0
  3. package/dist/auth/index.d.ts +7 -0
  4. package/dist/auth/index.d.ts.map +1 -0
  5. package/dist/auth/index.js +23 -0
  6. package/dist/auth/index.js.map +1 -0
  7. package/dist/auth/spotware-oauth-client.d.ts +31 -0
  8. package/dist/auth/spotware-oauth-client.d.ts.map +1 -0
  9. package/dist/auth/spotware-oauth-client.js +65 -0
  10. package/dist/auth/spotware-oauth-client.js.map +1 -0
  11. package/dist/auth/spotware-oauth-endpoints.d.ts +3 -0
  12. package/dist/auth/spotware-oauth-endpoints.d.ts.map +1 -0
  13. package/dist/auth/spotware-oauth-endpoints.js +8 -0
  14. package/dist/auth/spotware-oauth-endpoints.js.map +1 -0
  15. package/dist/auth/spotware-oauth-error.d.ts +6 -0
  16. package/dist/auth/spotware-oauth-error.d.ts.map +1 -0
  17. package/dist/auth/spotware-oauth-error.js +15 -0
  18. package/dist/auth/spotware-oauth-error.js.map +1 -0
  19. package/dist/auth/spotware-oauth-scope.enum.d.ts +5 -0
  20. package/dist/auth/spotware-oauth-scope.enum.d.ts.map +1 -0
  21. package/dist/auth/spotware-oauth-scope.enum.js +9 -0
  22. package/dist/auth/spotware-oauth-scope.enum.js.map +1 -0
  23. package/dist/auth/spotware-oauth-token.model.d.ts +7 -0
  24. package/dist/auth/spotware-oauth-token.model.d.ts.map +1 -0
  25. package/dist/auth/spotware-oauth-token.model.js +3 -0
  26. package/dist/auth/spotware-oauth-token.model.js.map +1 -0
  27. package/dist/auth/spotware-socket-auth-error.d.ts +5 -0
  28. package/dist/auth/spotware-socket-auth-error.d.ts.map +1 -0
  29. package/dist/auth/spotware-socket-auth-error.js +13 -0
  30. package/dist/auth/spotware-socket-auth-error.js.map +1 -0
  31. package/dist/auth/spotware-socket-authenticator.d.ts +21 -0
  32. package/dist/auth/spotware-socket-authenticator.d.ts.map +1 -0
  33. package/dist/auth/spotware-socket-authenticator.js +80 -0
  34. package/dist/auth/spotware-socket-authenticator.js.map +1 -0
  35. package/dist/client/index.d.ts +3 -0
  36. package/dist/client/index.d.ts.map +1 -0
  37. package/dist/client/index.js +19 -0
  38. package/dist/client/index.js.map +1 -0
  39. package/dist/client/spotware-client.d.ts +56 -0
  40. package/dist/client/spotware-client.d.ts.map +1 -0
  41. package/dist/client/spotware-client.js +172 -0
  42. package/dist/client/spotware-client.js.map +1 -0
  43. package/dist/client/spotware-request-error.d.ts +5 -0
  44. package/dist/client/spotware-request-error.d.ts.map +1 -0
  45. package/dist/client/spotware-request-error.js +13 -0
  46. package/dist/client/spotware-request-error.js.map +1 -0
  47. package/dist/example/example.d.ts +2 -0
  48. package/dist/example/example.d.ts.map +1 -0
  49. package/dist/example/example.js +187 -0
  50. package/dist/example/example.js.map +1 -0
  51. package/dist/example/market-data-example.d.ts +2 -0
  52. package/dist/example/market-data-example.d.ts.map +1 -0
  53. package/dist/example/market-data-example.js +32 -0
  54. package/dist/example/market-data-example.js.map +1 -0
  55. package/dist/example/shared/create-authenticated-client.d.ts +9 -0
  56. package/dist/example/shared/create-authenticated-client.d.ts.map +1 -0
  57. package/dist/example/shared/create-authenticated-client.js +154 -0
  58. package/dist/example/shared/create-authenticated-client.js.map +1 -0
  59. package/dist/example/trading-example.d.ts +2 -0
  60. package/dist/example/trading-example.d.ts.map +1 -0
  61. package/dist/example/trading-example.js +78 -0
  62. package/dist/example/trading-example.js.map +1 -0
  63. package/dist/index.d.ts +7 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +23 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/market-data/index.d.ts +3 -0
  68. package/dist/market-data/index.d.ts.map +1 -0
  69. package/dist/market-data/index.js +19 -0
  70. package/dist/market-data/index.js.map +1 -0
  71. package/dist/market-data/spotware-market-data.d.ts +31 -0
  72. package/dist/market-data/spotware-market-data.d.ts.map +1 -0
  73. package/dist/market-data/spotware-market-data.js +68 -0
  74. package/dist/market-data/spotware-market-data.js.map +1 -0
  75. package/dist/market-data/spotware-symbol-catalog.d.ts +19 -0
  76. package/dist/market-data/spotware-symbol-catalog.d.ts.map +1 -0
  77. package/dist/market-data/spotware-symbol-catalog.js +52 -0
  78. package/dist/market-data/spotware-symbol-catalog.js.map +1 -0
  79. package/dist/shared/sleep.d.ts +5 -0
  80. package/dist/shared/sleep.d.ts.map +1 -0
  81. package/dist/shared/sleep.js +17 -0
  82. package/dist/shared/sleep.js.map +1 -0
  83. package/dist/shared/spotware-scale.d.ts +3 -0
  84. package/dist/shared/spotware-scale.d.ts.map +1 -0
  85. package/dist/shared/spotware-scale.js +12 -0
  86. package/dist/shared/spotware-scale.js.map +1 -0
  87. package/dist/shared/typed-event-emitter.d.ts +13 -0
  88. package/dist/shared/typed-event-emitter.d.ts.map +1 -0
  89. package/dist/shared/typed-event-emitter.js +28 -0
  90. package/dist/shared/typed-event-emitter.js.map +1 -0
  91. package/dist/trading/index.d.ts +2 -0
  92. package/dist/trading/index.d.ts.map +1 -0
  93. package/dist/trading/index.js +18 -0
  94. package/dist/trading/index.js.map +1 -0
  95. package/dist/trading/spotware-trading.d.ts +59 -0
  96. package/dist/trading/spotware-trading.d.ts.map +1 -0
  97. package/dist/trading/spotware-trading.js +97 -0
  98. package/dist/trading/spotware-trading.js.map +1 -0
  99. package/dist/transport/frame-codec.d.ts +6 -0
  100. package/dist/transport/frame-codec.d.ts.map +1 -0
  101. package/dist/transport/frame-codec.js +35 -0
  102. package/dist/transport/frame-codec.js.map +1 -0
  103. package/dist/transport/index.d.ts +4 -0
  104. package/dist/transport/index.d.ts.map +1 -0
  105. package/dist/transport/index.js +20 -0
  106. package/dist/transport/index.js.map +1 -0
  107. package/dist/transport/rate-limiter.d.ts +11 -0
  108. package/dist/transport/rate-limiter.d.ts.map +1 -0
  109. package/dist/transport/rate-limiter.js +48 -0
  110. package/dist/transport/rate-limiter.js.map +1 -0
  111. package/dist/transport/reconnect-backoff.d.ts +12 -0
  112. package/dist/transport/reconnect-backoff.d.ts.map +1 -0
  113. package/dist/transport/reconnect-backoff.js +20 -0
  114. package/dist/transport/reconnect-backoff.js.map +1 -0
  115. package/dist/transport/spotware-host.enum.d.ts +6 -0
  116. package/dist/transport/spotware-host.enum.d.ts.map +1 -0
  117. package/dist/transport/spotware-host.enum.js +10 -0
  118. package/dist/transport/spotware-host.enum.js.map +1 -0
  119. package/dist/transport/spotware-rate-limiter.d.ts +8 -0
  120. package/dist/transport/spotware-rate-limiter.d.ts.map +1 -0
  121. package/dist/transport/spotware-rate-limiter.js +29 -0
  122. package/dist/transport/spotware-rate-limiter.js.map +1 -0
  123. package/dist/transport/spotware-transport.d.ts +63 -0
  124. package/dist/transport/spotware-transport.d.ts.map +1 -0
  125. package/dist/transport/spotware-transport.js +237 -0
  126. package/dist/transport/spotware-transport.js.map +1 -0
  127. package/dist/types/generated/OpenApiCommonMessages.d.ts +49 -0
  128. package/dist/types/generated/OpenApiCommonMessages.d.ts.map +1 -0
  129. package/dist/types/generated/OpenApiCommonMessages.js +285 -0
  130. package/dist/types/generated/OpenApiCommonMessages.js.map +1 -0
  131. package/dist/types/generated/OpenApiCommonModelMessages.d.ts +40 -0
  132. package/dist/types/generated/OpenApiCommonModelMessages.d.ts.map +1 -0
  133. package/dist/types/generated/OpenApiCommonModelMessages.js +140 -0
  134. package/dist/types/generated/OpenApiCommonModelMessages.js.map +1 -0
  135. package/dist/types/generated/OpenApiMessages.d.ts +964 -0
  136. package/dist/types/generated/OpenApiMessages.d.ts.map +1 -0
  137. package/dist/types/generated/OpenApiMessages.js +8754 -0
  138. package/dist/types/generated/OpenApiMessages.js.map +1 -0
  139. package/dist/types/generated/OpenApiModelMessages.d.ts +1116 -0
  140. package/dist/types/generated/OpenApiModelMessages.d.ts.map +1 -0
  141. package/dist/types/generated/OpenApiModelMessages.js +6917 -0
  142. package/dist/types/generated/OpenApiModelMessages.js.map +1 -0
  143. package/dist/types/index.d.ts +5 -0
  144. package/dist/types/index.d.ts.map +1 -0
  145. package/dist/types/index.js +141 -0
  146. package/dist/types/index.js.map +1 -0
  147. package/package.json +61 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Caius Citiriga
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # ctrader-x
2
+
3
+ A TypeScript SDK for cTrader's Open API — connect, authenticate, stream prices, and trade, with automatic reconnection built in.
4
+
5
+ ## Why
6
+
7
+ There is no official Spotware SDK for Node.js/TypeScript; official support covers mainly C# and Python. The main community alternative, Mida, went closed-source. Developers integrating the Open API directly hit real, documented friction: a raw TCP/Protobuf protocol with manual message framing, a delegated OAuth2 handshake, and enough moving parts that getting from zero to a connected, authenticated, streaming client takes real effort.
8
+
9
+ ctrader-x exists to remove that friction: a clean, typed, batteries-included client, with resilience (reconnection, backoff, outage detection) handled for you instead of left as an exercise.
10
+
11
+ This is a connectivity/SDK library, not a dashboard or a UI. It gives you the building blocks to talk to cTrader's Open API from your own Node.js backend.
12
+
13
+ ## Features
14
+
15
+ - Fully typed, generated directly from Spotware's official `.proto` definitions — no hand-maintained protocol types to drift out of date.
16
+ - A TCP/TLS transport that survives real network outages: automatic reconnection with exponential backoff and jitter, a liveness watchdog that notices a silently dead connection before the OS would, and Spotware's documented rate limits enforced automatically.
17
+ - OAuth2 authorization flow plus the socket-level authentication handshake, re-run automatically after every reconnect.
18
+ - Request/response correlation, so `client.send(...)` resolves or rejects with the matching response instead of requiring you to track `clientMsgId`s yourself.
19
+ - Market data subscriptions with automatic resubscription after a reconnect, and a symbol catalog you can use standalone.
20
+ - Order placement, amendment, cancellation, position closing, and querying open positions/pending orders.
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ npm install ctrader-x
26
+ ```
27
+
28
+ Requires Node.js 18 or later.
29
+
30
+ ## Prerequisites
31
+
32
+ Before writing any code, register an application in the [cTrader Open API portal](https://help.ctrader.com/open-api/) to obtain a `clientId` and `clientSecret`, and register a redirect URI for the OAuth2 flow (e.g. `http://localhost:3939/callback`). You'll also need at least one demo account linked to your cTID to test against — start on `SpotwareHost.DEMO`, not `SpotwareHost.LIVE`, until you're confident in your integration.
33
+
34
+ ## Quick start
35
+
36
+ The fastest way to see it working end to end — browser login and all — is the included example:
37
+
38
+ ```bash
39
+ git clone git@github.com:caiusCitiriga/ctrader-x.git
40
+ cd ctrader-x
41
+ npm install
42
+ npm start
43
+ ```
44
+
45
+ ### Connecting in your own code
46
+
47
+ Once you have an access token and know which account you're connecting to (see [Authenticating](#authenticating-for-the-first-time) below), connecting is this:
48
+
49
+ ```typescript
50
+ import { SpotwareClient, SpotwareHost, SpotwareOAuthClient, SpotwareTransport } from 'ctrader-x';
51
+
52
+ const oauthClient = new SpotwareOAuthClient({ clientId, clientSecret });
53
+
54
+ const client = new SpotwareClient({
55
+ transport: new SpotwareTransport({ host: SpotwareHost.DEMO }),
56
+ oauthClient,
57
+ clientId,
58
+ clientSecret,
59
+ ctidTraderAccountId, // the account you're connecting to
60
+ token // { accessToken, refreshToken, tokenType, expiresIn }
61
+ });
62
+
63
+ await client.connect();
64
+ ```
65
+
66
+ That's it — `client` re-authenticates automatically after every reconnect and refreshes the token when it's close to expiring. It's now ready to use with the `market-data` and `trading` modules below.
67
+
68
+ ### Authenticating for the first time
69
+
70
+ Getting that `token` and `ctidTraderAccountId` the very first time is a one-time OAuth2 flow, not something you do on every run:
71
+
72
+ 1. Build an authorization URL and send the user to it in a browser.
73
+ 2. They log into cTrader and approve access; cTrader redirects back to your `redirectUri` with a `code` query param.
74
+ 3. Exchange that code for a token.
75
+ 4. Ask the server which account(s) that token can access, and pick one.
76
+
77
+ ```typescript
78
+ const oauthClient = new SpotwareOAuthClient({ clientId, clientSecret });
79
+ const authorizeUrl = oauthClient.buildAuthorizationUrl({ redirectUri, scope: SpotwareOAuthScope.TRADING });
80
+ // open authorizeUrl in a browser, then capture the `code` param cTrader redirects back with
81
+ const token = await oauthClient.exchangeAuthorizationCode({ code, redirectUri });
82
+ ```
83
+
84
+ Step 4 (listing accounts) needs a connected `SpotwareTransport` and a `SpotwareSocketAuthenticator` — rather than duplicate that here, see [`src/example/shared/create-authenticated-client.ts`](src/example/shared/create-authenticated-client.ts) for the complete, runnable version: capturing the redirect with a local HTTP server, discovering linked accounts, and persisting the token to disk. Refresh tokens are single-use, so save the replacement `token` every time `client.on('tokenRefreshed', ...)` fires, or the next run will fail.
85
+
86
+ ## Architecture
87
+
88
+ Dependencies only flow one direction, top to bottom in this table: `trading` and `market-data` depend on `client`, which depends on `transport` and `auth`, which depends on `types`. It never goes the other way — `types` has no idea `trading` exists.
89
+
90
+ | Module | Depends on | Responsibility |
91
+ | ------------- | ----------------- | ---------------------------------------------------------------------------------------- |
92
+ | `types` | — | Generated TypeScript types for every Open API Protobuf message. |
93
+ | `transport` | `types` | TCP/TLS connection, message framing, reconnection, rate limiting. |
94
+ | `auth` | `transport` | OAuth2 token flow and the socket-level auth handshake. |
95
+ | `client` | `transport`, `auth`| Request/response correlation, re-auth on reconnect, token refresh. |
96
+ | `market-data` | `client` | Symbol lookup and spot price subscriptions. |
97
+ | `trading` | `client` | Order placement, amendment, cancellation, and position/order queries. |
98
+
99
+ ## Usage
100
+
101
+ ### Market data
102
+
103
+ ```typescript
104
+ import { SpotwareMarketData } from 'ctrader-x';
105
+
106
+ const marketData = new SpotwareMarketData(client);
107
+
108
+ marketData.on('price', (update) => {
109
+ console.log(`${update.symbolId}: bid=${update.bid} ask=${update.ask}`);
110
+ });
111
+
112
+ const symbol = await marketData.symbols.findByName('EURUSD');
113
+ if (symbol) {
114
+ await marketData.subscribe(symbol.symbolId);
115
+ }
116
+ ```
117
+
118
+ `marketData.symbols` is a `SpotwareSymbolCatalog` — it can also be used on its own (`new SpotwareSymbolCatalog(client)`) if you only need symbol lookups.
119
+
120
+ ### Trading
121
+
122
+ ```typescript
123
+ import { SpotwareTrading, ProtoOATradeSide } from 'ctrader-x';
124
+
125
+ const trading = new SpotwareTrading(client);
126
+
127
+ const execution = await trading.placeMarketOrder({
128
+ symbolId: symbol.symbolId,
129
+ tradeSide: ProtoOATradeSide.BUY,
130
+ volume: 1000 // 1000 units, not lots — see "A note on volume" below
131
+ });
132
+
133
+ const { positions, orders } = await trading.getOpenPositionsAndOrders();
134
+ ```
135
+
136
+ #### A note on volume
137
+
138
+ `volume` here is in **units** of the symbol's base currency (for EURUSD, 1 unit = 1 EUR), not lots. On the wire, cTrader represents volume as "cents of a unit" — `100000` means `1000.00` units — and `trading` converts to and from that form for you, so you always work in whole units through this API, never the wire's scaled integer.
139
+
140
+ Units and lots are not the same thing, and the conversion between them is **not a fixed ratio you can hardcode**. How many units make up "1 lot" is defined per symbol, not by the protocol — retail forex conventionally uses 100,000 units per lot, but that's a market convention, not something cTrader's API guarantees for every symbol (it can differ for indices, commodities, crypto, or simply per broker). The authoritative values — `lotSize`, plus the tradable `minVolume`/`maxVolume`/`stepVolume` range — live on the full symbol spec (`ProtoOASymbol`, fetched via `PROTO_OA_SYMBOL_BY_ID_REQ`), not on the lighter `ProtoOALightSymbol` that `SpotwareSymbolCatalog` currently exposes. If your UI works in lots, fetch that full spec yourself and convert before calling `trading`; `ctrader-x` doesn't wrap that request yet.
141
+
142
+ More complete, runnable examples live in [`src/example/`](src/example/):
143
+
144
+ ```bash
145
+ npm run start:market-data # subscribe to a symbol and print live prices
146
+ npm run start:trading # query positions/orders, place and cancel a safe limit order
147
+ ```
148
+
149
+ ## Development
150
+
151
+ ### Running tests
152
+
153
+ ```bash
154
+ npm test
155
+ ```
156
+
157
+ ### Building
158
+
159
+ ```bash
160
+ npm run build
161
+ ```
162
+
163
+ ### Regenerating protocol types
164
+
165
+ `src/types/generated` is produced from Spotware's official `.proto` files in [`proto/`](proto) via `ts-proto`, and is committed to the repo. Whenever `proto/` is refreshed from Spotware's upstream repo, regenerate and commit the diff:
166
+
167
+ ```bash
168
+ npm run generate:types
169
+ ```
170
+
171
+ ## Contributing
172
+
173
+ Issues and pull requests are welcome. Please open an issue to discuss significant changes before submitting a PR.
174
+
175
+ ## License
176
+
177
+ [MIT](LICENSE)
@@ -0,0 +1,7 @@
1
+ export * from './spotware-oauth-client';
2
+ export * from './spotware-oauth-error';
3
+ export * from './spotware-oauth-scope.enum';
4
+ export * from './spotware-oauth-token.model';
5
+ export * from './spotware-socket-auth-error';
6
+ export * from './spotware-socket-authenticator';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./spotware-oauth-client"), exports);
18
+ __exportStar(require("./spotware-oauth-error"), exports);
19
+ __exportStar(require("./spotware-oauth-scope.enum"), exports);
20
+ __exportStar(require("./spotware-oauth-token.model"), exports);
21
+ __exportStar(require("./spotware-socket-auth-error"), exports);
22
+ __exportStar(require("./spotware-socket-authenticator"), exports);
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0DAAwC;AACxC,yDAAuC;AACvC,8DAA4C;AAC5C,+DAA6C;AAC7C,+DAA6C;AAC7C,kEAAgD"}
@@ -0,0 +1,31 @@
1
+ import { SpotwareOAuthScope } from './spotware-oauth-scope.enum';
2
+ import type { ISpotwareOAuthToken } from './spotware-oauth-token.model';
3
+ export interface ISpotwareOAuthClientOptions {
4
+ clientId: string;
5
+ clientSecret: string;
6
+ }
7
+ export interface IBuildAuthorizationUrlParams {
8
+ redirectUri: string;
9
+ scope: SpotwareOAuthScope;
10
+ }
11
+ export interface IExchangeAuthorizationCodeParams {
12
+ code: string;
13
+ redirectUri: string;
14
+ }
15
+ export interface IRefreshAccessTokenParams {
16
+ refreshToken: string;
17
+ }
18
+ /**
19
+ * The HTTP half of the OAuth2 flow: builds the authorization URL, exchanges the
20
+ * redirect code for tokens, and refreshes the access token. Knows nothing about
21
+ * the TCP socket or the ApplicationAuthReq/AccountAuthReq handshake.
22
+ */
23
+ export declare class SpotwareOAuthClient {
24
+ private readonly options;
25
+ constructor(options: ISpotwareOAuthClientOptions);
26
+ buildAuthorizationUrl({ redirectUri, scope }: IBuildAuthorizationUrlParams): string;
27
+ exchangeAuthorizationCode({ code, redirectUri }: IExchangeAuthorizationCodeParams): Promise<ISpotwareOAuthToken>;
28
+ refreshAccessToken({ refreshToken }: IRefreshAccessTokenParams): Promise<ISpotwareOAuthToken>;
29
+ private requestToken;
30
+ }
31
+ //# sourceMappingURL=spotware-oauth-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spotware-oauth-client.d.ts","sourceRoot":"","sources":["../../src/auth/spotware-oauth-client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAExE,MAAM,WAAW,2BAA2B;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,4BAA4B;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,kBAAkB,CAAC;CAC7B;AAED,MAAM,WAAW,gCAAgC;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,yBAAyB;IACtC,YAAY,EAAE,MAAM,CAAC;CACxB;AAWD;;;;GAIG;AACH,qBAAa,mBAAmB;IAChB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,2BAA2B;IAEjE,qBAAqB,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,4BAA4B,GAAG,MAAM;IASnF,yBAAyB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,gCAAgC,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAQhH,kBAAkB,CAAC,EAAE,YAAY,EAAE,EAAE,yBAAyB,GAAG,OAAO,CAAC,mBAAmB,CAAC;YAS/E,YAAY;CAgC7B"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SpotwareOAuthClient = void 0;
4
+ const spotware_oauth_endpoints_1 = require("./spotware-oauth-endpoints");
5
+ const spotware_oauth_error_1 = require("./spotware-oauth-error");
6
+ /**
7
+ * The HTTP half of the OAuth2 flow: builds the authorization URL, exchanges the
8
+ * redirect code for tokens, and refreshes the access token. Knows nothing about
9
+ * the TCP socket or the ApplicationAuthReq/AccountAuthReq handshake.
10
+ */
11
+ class SpotwareOAuthClient {
12
+ options;
13
+ constructor(options) {
14
+ this.options = options;
15
+ }
16
+ buildAuthorizationUrl({ redirectUri, scope }) {
17
+ const url = new URL(spotware_oauth_endpoints_1.SPOTWARE_OAUTH_AUTHORIZE_URL);
18
+ url.searchParams.set('client_id', this.options.clientId);
19
+ url.searchParams.set('redirect_uri', redirectUri);
20
+ url.searchParams.set('scope', scope);
21
+ return url.toString();
22
+ }
23
+ exchangeAuthorizationCode({ code, redirectUri }) {
24
+ return this.requestToken({
25
+ grant_type: 'authorization_code',
26
+ code,
27
+ redirect_uri: redirectUri
28
+ });
29
+ }
30
+ refreshAccessToken({ refreshToken }) {
31
+ return this.requestToken({
32
+ grant_type: 'refresh_token',
33
+ refresh_token: refreshToken
34
+ });
35
+ }
36
+ // Spotware's token endpoint takes these as GET query params, client_secret included,
37
+ // matching their own SDKs. Not our choice of contract, just theirs to interop with.
38
+ async requestToken(params) {
39
+ const url = new URL(spotware_oauth_endpoints_1.SPOTWARE_OAUTH_TOKEN_URL);
40
+ for (const [key, value] of Object.entries(params)) {
41
+ url.searchParams.set(key, value);
42
+ }
43
+ url.searchParams.set('client_id', this.options.clientId);
44
+ url.searchParams.set('client_secret', this.options.clientSecret);
45
+ let response;
46
+ try {
47
+ response = await fetch(url);
48
+ }
49
+ catch (error) {
50
+ throw new spotware_oauth_error_1.SpotwareOAuthError(`Failed to reach the Spotware token endpoint: ${error.message}`);
51
+ }
52
+ const payload = (await response.json());
53
+ if (!response.ok || !payload.accessToken || !payload.refreshToken) {
54
+ throw new spotware_oauth_error_1.SpotwareOAuthError(payload.description ?? `Spotware token request failed with HTTP ${response.status}`, payload.errorCode, response.status);
55
+ }
56
+ return {
57
+ accessToken: payload.accessToken,
58
+ refreshToken: payload.refreshToken,
59
+ tokenType: payload.tokenType ?? 'bearer',
60
+ expiresIn: payload.expiresIn ?? 0
61
+ };
62
+ }
63
+ }
64
+ exports.SpotwareOAuthClient = SpotwareOAuthClient;
65
+ //# sourceMappingURL=spotware-oauth-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spotware-oauth-client.js","sourceRoot":"","sources":["../../src/auth/spotware-oauth-client.ts"],"names":[],"mappings":";;;AAAA,yEAAoG;AACpG,iEAA4D;AAgC5D;;;;GAIG;AACH,MAAa,mBAAmB;IACC;IAA7B,YAA6B,OAAoC;QAApC,YAAO,GAAP,OAAO,CAA6B;IAAG,CAAC;IAErE,qBAAqB,CAAC,EAAE,WAAW,EAAE,KAAK,EAAgC;QACtE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,uDAA4B,CAAC,CAAC;QAClD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACzD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;QAClD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAErC,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IAED,yBAAyB,CAAC,EAAE,IAAI,EAAE,WAAW,EAAoC;QAC7E,OAAO,IAAI,CAAC,YAAY,CAAC;YACrB,UAAU,EAAE,oBAAoB;YAChC,IAAI;YACJ,YAAY,EAAE,WAAW;SAC5B,CAAC,CAAC;IACP,CAAC;IAED,kBAAkB,CAAC,EAAE,YAAY,EAA6B;QAC1D,OAAO,IAAI,CAAC,YAAY,CAAC;YACrB,UAAU,EAAE,eAAe;YAC3B,aAAa,EAAE,YAAY;SAC9B,CAAC,CAAC;IACP,CAAC;IAED,qFAAqF;IACrF,oFAAoF;IAC5E,KAAK,CAAC,YAAY,CAAC,MAA8B;QACrD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,mDAAwB,CAAC,CAAC;QAC9C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAChD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;QACD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACzD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAEjE,IAAI,QAAkB,CAAC;QACvB,IAAI,CAAC;YACD,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,IAAI,yCAAkB,CAAC,gDAAiD,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7G,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAkC,CAAC;QAEzE,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;YAChE,MAAM,IAAI,yCAAkB,CACxB,OAAO,CAAC,WAAW,IAAI,2CAA2C,QAAQ,CAAC,MAAM,EAAE,EACnF,OAAO,CAAC,SAAS,EACjB,QAAQ,CAAC,MAAM,CAClB,CAAC;QACN,CAAC;QAED,OAAO;YACH,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,QAAQ;YACxC,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,CAAC;SACpC,CAAC;IACN,CAAC;CACJ;AA7DD,kDA6DC"}
@@ -0,0 +1,3 @@
1
+ export declare const SPOTWARE_OAUTH_AUTHORIZE_URL = "https://openapi.ctrader.com/apps/auth";
2
+ export declare const SPOTWARE_OAUTH_TOKEN_URL = "https://openapi.ctrader.com/apps/token";
3
+ //# sourceMappingURL=spotware-oauth-endpoints.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spotware-oauth-endpoints.d.ts","sourceRoot":"","sources":["../../src/auth/spotware-oauth-endpoints.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,4BAA4B,0CAA0C,CAAC;AACpF,eAAO,MAAM,wBAAwB,2CAA2C,CAAC"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SPOTWARE_OAUTH_TOKEN_URL = exports.SPOTWARE_OAUTH_AUTHORIZE_URL = void 0;
4
+ // Confirmed against Spotware's own OpenApiPy SDK source, not the (partly stale) prose docs:
5
+ // https://github.com/spotware/OpenApiPy/blob/main/ctrader_open_api/endpoints.py
6
+ exports.SPOTWARE_OAUTH_AUTHORIZE_URL = 'https://openapi.ctrader.com/apps/auth';
7
+ exports.SPOTWARE_OAUTH_TOKEN_URL = 'https://openapi.ctrader.com/apps/token';
8
+ //# sourceMappingURL=spotware-oauth-endpoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spotware-oauth-endpoints.js","sourceRoot":"","sources":["../../src/auth/spotware-oauth-endpoints.ts"],"names":[],"mappings":";;;AAAA,4FAA4F;AAC5F,gFAAgF;AACnE,QAAA,4BAA4B,GAAG,uCAAuC,CAAC;AACvE,QAAA,wBAAwB,GAAG,wCAAwC,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare class SpotwareOAuthError extends Error {
2
+ readonly errorCode?: string | undefined;
3
+ readonly httpStatus?: number | undefined;
4
+ constructor(message: string, errorCode?: string | undefined, httpStatus?: number | undefined);
5
+ }
6
+ //# sourceMappingURL=spotware-oauth-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spotware-oauth-error.d.ts","sourceRoot":"","sources":["../../src/auth/spotware-oauth-error.ts"],"names":[],"mappings":"AAAA,qBAAa,kBAAmB,SAAQ,KAAK;aAGrB,SAAS,CAAC,EAAE,MAAM;aAClB,UAAU,CAAC,EAAE,MAAM;gBAFnC,OAAO,EAAE,MAAM,EACC,SAAS,CAAC,EAAE,MAAM,YAAA,EAClB,UAAU,CAAC,EAAE,MAAM,YAAA;CAK1C"}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SpotwareOAuthError = void 0;
4
+ class SpotwareOAuthError extends Error {
5
+ errorCode;
6
+ httpStatus;
7
+ constructor(message, errorCode, httpStatus) {
8
+ super(message);
9
+ this.errorCode = errorCode;
10
+ this.httpStatus = httpStatus;
11
+ this.name = 'SpotwareOAuthError';
12
+ }
13
+ }
14
+ exports.SpotwareOAuthError = SpotwareOAuthError;
15
+ //# sourceMappingURL=spotware-oauth-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spotware-oauth-error.js","sourceRoot":"","sources":["../../src/auth/spotware-oauth-error.ts"],"names":[],"mappings":";;;AAAA,MAAa,kBAAmB,SAAQ,KAAK;IAGrB;IACA;IAHpB,YACI,OAAe,EACC,SAAkB,EAClB,UAAmB;QAEnC,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,cAAS,GAAT,SAAS,CAAS;QAClB,eAAU,GAAV,UAAU,CAAS;QAGnC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACrC,CAAC;CACJ;AATD,gDASC"}
@@ -0,0 +1,5 @@
1
+ export declare enum SpotwareOAuthScope {
2
+ ACCOUNTS = "accounts",
3
+ TRADING = "trading"
4
+ }
5
+ //# sourceMappingURL=spotware-oauth-scope.enum.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spotware-oauth-scope.enum.d.ts","sourceRoot":"","sources":["../../src/auth/spotware-oauth-scope.enum.ts"],"names":[],"mappings":"AAAA,oBAAY,kBAAkB;IAC1B,QAAQ,aAAa;IACrB,OAAO,YAAY;CACtB"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SpotwareOAuthScope = void 0;
4
+ var SpotwareOAuthScope;
5
+ (function (SpotwareOAuthScope) {
6
+ SpotwareOAuthScope["ACCOUNTS"] = "accounts";
7
+ SpotwareOAuthScope["TRADING"] = "trading";
8
+ })(SpotwareOAuthScope || (exports.SpotwareOAuthScope = SpotwareOAuthScope = {}));
9
+ //# sourceMappingURL=spotware-oauth-scope.enum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spotware-oauth-scope.enum.js","sourceRoot":"","sources":["../../src/auth/spotware-oauth-scope.enum.ts"],"names":[],"mappings":";;;AAAA,IAAY,kBAGX;AAHD,WAAY,kBAAkB;IAC1B,2CAAqB,CAAA;IACrB,yCAAmB,CAAA;AACvB,CAAC,EAHW,kBAAkB,kCAAlB,kBAAkB,QAG7B"}
@@ -0,0 +1,7 @@
1
+ export interface ISpotwareOAuthToken {
2
+ accessToken: string;
3
+ refreshToken: string;
4
+ tokenType: string;
5
+ expiresIn: number;
6
+ }
7
+ //# sourceMappingURL=spotware-oauth-token.model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spotware-oauth-token.model.d.ts","sourceRoot":"","sources":["../../src/auth/spotware-oauth-token.model.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACrB"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=spotware-oauth-token.model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spotware-oauth-token.model.js","sourceRoot":"","sources":["../../src/auth/spotware-oauth-token.model.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ export declare class SpotwareSocketAuthError extends Error {
2
+ readonly errorCode?: string | undefined;
3
+ constructor(message: string, errorCode?: string | undefined);
4
+ }
5
+ //# sourceMappingURL=spotware-socket-auth-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spotware-socket-auth-error.d.ts","sourceRoot":"","sources":["../../src/auth/spotware-socket-auth-error.ts"],"names":[],"mappings":"AAAA,qBAAa,uBAAwB,SAAQ,KAAK;aAG1B,SAAS,CAAC,EAAE,MAAM;gBADlC,OAAO,EAAE,MAAM,EACC,SAAS,CAAC,EAAE,MAAM,YAAA;CAKzC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SpotwareSocketAuthError = void 0;
4
+ class SpotwareSocketAuthError extends Error {
5
+ errorCode;
6
+ constructor(message, errorCode) {
7
+ super(message);
8
+ this.errorCode = errorCode;
9
+ this.name = 'SpotwareSocketAuthError';
10
+ }
11
+ }
12
+ exports.SpotwareSocketAuthError = SpotwareSocketAuthError;
13
+ //# sourceMappingURL=spotware-socket-auth-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spotware-socket-auth-error.js","sourceRoot":"","sources":["../../src/auth/spotware-socket-auth-error.ts"],"names":[],"mappings":";;;AAAA,MAAa,uBAAwB,SAAQ,KAAK;IAG1B;IAFpB,YACI,OAAe,EACC,SAAkB;QAElC,KAAK,CAAC,OAAO,CAAC,CAAC;QAFC,cAAS,GAAT,SAAS,CAAS;QAGlC,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IAC1C,CAAC;CACJ;AARD,0DAQC"}
@@ -0,0 +1,21 @@
1
+ import type { SpotwareTransport } from '../transport';
2
+ import { ProtoOACtidTraderAccount } from '../types';
3
+ export interface ISpotwareSocketAuthenticatorOptions {
4
+ responseTimeoutMs?: number;
5
+ }
6
+ /**
7
+ * The socket half of the auth flow: ApplicationAuthReq, then GetAccountListByAccessTokenReq
8
+ * (the only way to discover a ctidTraderAccountId from a bare access token), then
9
+ * AccountAuthReq. Requires an already-connected transport; knows nothing about how the
10
+ * access token itself was obtained.
11
+ */
12
+ export declare class SpotwareSocketAuthenticator {
13
+ private readonly transport;
14
+ private readonly responseTimeoutMs;
15
+ constructor(transport: SpotwareTransport, options?: ISpotwareSocketAuthenticatorOptions);
16
+ authenticateApplication(clientId: string, clientSecret: string): Promise<void>;
17
+ listAccounts(accessToken: string): Promise<ProtoOACtidTraderAccount[]>;
18
+ authenticateAccount(ctidTraderAccountId: number, accessToken: string): Promise<void>;
19
+ private sendAndAwait;
20
+ }
21
+ //# sourceMappingURL=spotware-socket-authenticator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spotware-socket-authenticator.d.ts","sourceRoot":"","sources":["../../src/auth/spotware-socket-authenticator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAIH,wBAAwB,EAO3B,MAAM,UAAU,CAAC;AAKlB,MAAM,WAAW,mCAAmC;IAChD,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,qBAAa,2BAA2B;IAIhC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAH9B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;gBAGtB,SAAS,EAAE,iBAAiB,EAC7C,OAAO,GAAE,mCAAwC;IAK/C,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY9E,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,EAAE,CAAC;IActE,mBAAmB,CAAC,mBAAmB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAY1F,OAAO,CAAC,YAAY;CA0CvB"}
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SpotwareSocketAuthenticator = void 0;
4
+ const types_1 = require("../types");
5
+ const spotware_socket_auth_error_1 = require("./spotware-socket-auth-error");
6
+ const DEFAULT_RESPONSE_TIMEOUT_MS = 10_000;
7
+ /**
8
+ * The socket half of the auth flow: ApplicationAuthReq, then GetAccountListByAccessTokenReq
9
+ * (the only way to discover a ctidTraderAccountId from a bare access token), then
10
+ * AccountAuthReq. Requires an already-connected transport; knows nothing about how the
11
+ * access token itself was obtained.
12
+ */
13
+ class SpotwareSocketAuthenticator {
14
+ transport;
15
+ responseTimeoutMs;
16
+ constructor(transport, options = {}) {
17
+ this.transport = transport;
18
+ this.responseTimeoutMs = options.responseTimeoutMs ?? DEFAULT_RESPONSE_TIMEOUT_MS;
19
+ }
20
+ async authenticateApplication(clientId, clientSecret) {
21
+ const request = types_1.ProtoOAApplicationAuthReq.fromPartial({ clientId, clientSecret });
22
+ await this.sendAndAwait(types_1.ProtoMessage.fromPartial({
23
+ payloadType: types_1.ProtoOAPayloadType.PROTO_OA_APPLICATION_AUTH_REQ,
24
+ payload: types_1.ProtoOAApplicationAuthReq.encode(request).finish()
25
+ }), types_1.ProtoOAPayloadType.PROTO_OA_APPLICATION_AUTH_RES);
26
+ }
27
+ async listAccounts(accessToken) {
28
+ const request = types_1.ProtoOAGetAccountListByAccessTokenReq.fromPartial({ accessToken });
29
+ const response = await this.sendAndAwait(types_1.ProtoMessage.fromPartial({
30
+ payloadType: types_1.ProtoOAPayloadType.PROTO_OA_GET_ACCOUNTS_BY_ACCESS_TOKEN_REQ,
31
+ payload: types_1.ProtoOAGetAccountListByAccessTokenReq.encode(request).finish()
32
+ }), types_1.ProtoOAPayloadType.PROTO_OA_GET_ACCOUNTS_BY_ACCESS_TOKEN_RES);
33
+ return types_1.ProtoOAGetAccountListByAccessTokenRes.decode(response.payload ?? new Uint8Array()).ctidTraderAccount;
34
+ }
35
+ async authenticateAccount(ctidTraderAccountId, accessToken) {
36
+ const request = types_1.ProtoOAAccountAuthReq.fromPartial({ ctidTraderAccountId, accessToken });
37
+ await this.sendAndAwait(types_1.ProtoMessage.fromPartial({
38
+ payloadType: types_1.ProtoOAPayloadType.PROTO_OA_ACCOUNT_AUTH_REQ,
39
+ payload: types_1.ProtoOAAccountAuthReq.encode(request).finish()
40
+ }), types_1.ProtoOAPayloadType.PROTO_OA_ACCOUNT_AUTH_RES);
41
+ }
42
+ sendAndAwait(message, expectedPayloadType) {
43
+ return new Promise((resolve, reject) => {
44
+ let timeout;
45
+ const cleanup = () => {
46
+ clearTimeout(timeout);
47
+ this.transport.off('message', onMessage);
48
+ };
49
+ const onMessage = (received) => {
50
+ if (received.payloadType === expectedPayloadType) {
51
+ cleanup();
52
+ resolve(received);
53
+ return;
54
+ }
55
+ if (received.payloadType === types_1.ProtoOAPayloadType.PROTO_OA_ERROR_RES) {
56
+ const error = types_1.ProtoOAErrorRes.decode(received.payload ?? new Uint8Array());
57
+ cleanup();
58
+ reject(new spotware_socket_auth_error_1.SpotwareSocketAuthError(error.description ?? error.errorCode, error.errorCode));
59
+ return;
60
+ }
61
+ if (received.payloadType === types_1.ProtoPayloadType.ERROR_RES) {
62
+ const error = types_1.ProtoErrorRes.decode(received.payload ?? new Uint8Array());
63
+ cleanup();
64
+ reject(new spotware_socket_auth_error_1.SpotwareSocketAuthError(error.description ?? error.errorCode, error.errorCode));
65
+ }
66
+ };
67
+ timeout = setTimeout(() => {
68
+ cleanup();
69
+ reject(new spotware_socket_auth_error_1.SpotwareSocketAuthError(`Timed out waiting for payloadType ${expectedPayloadType}`));
70
+ }, this.responseTimeoutMs);
71
+ this.transport.on('message', onMessage);
72
+ this.transport.send(message).catch((error) => {
73
+ cleanup();
74
+ reject(error);
75
+ });
76
+ });
77
+ }
78
+ }
79
+ exports.SpotwareSocketAuthenticator = SpotwareSocketAuthenticator;
80
+ //# sourceMappingURL=spotware-socket-authenticator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spotware-socket-authenticator.js","sourceRoot":"","sources":["../../src/auth/spotware-socket-authenticator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export * from './spotware-client';
2
+ export * from './spotware-request-error';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./spotware-client"), exports);
18
+ __exportStar(require("./spotware-request-error"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,2DAAyC"}