@danielgroen/dxtrade-api 1.0.23 → 1.0.24
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/README.md +65 -41
- package/dist/index.d.mts +130 -55
- package/dist/index.d.ts +130 -55
- package/dist/index.js +284 -106
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +284 -106
- package/dist/index.mjs.map +1 -1
- package/llms.txt +38 -30
- package/package.json +17 -17
package/dist/index.js
CHANGED
|
@@ -66,7 +66,7 @@ var endpoints = {
|
|
|
66
66
|
assessments: (base) => `${base}/api/assessments`,
|
|
67
67
|
websocket: (base, atmosphereId) => `wss://${base.split("//")[1]}/client/connector` + websocketQuery(atmosphereId),
|
|
68
68
|
tradeJournal: (base, params) => `${base}/api/tradejournal?from=${params.from}&to=${params.to}`,
|
|
69
|
-
tradeHistory: (base, params) => `${base}/api/history?from=${params.from}&to=${params.to}
|
|
69
|
+
tradeHistory: (base, params) => `${base}/api/history?from=${params.from}&to=${params.to}`,
|
|
70
70
|
subscribeInstruments: (base) => `${base}/api/instruments/subscribeInstrumentSymbols`,
|
|
71
71
|
charts: (base) => `${base}/api/charts`
|
|
72
72
|
};
|
|
@@ -125,6 +125,9 @@ var ERROR = /* @__PURE__ */ ((ERROR2) => {
|
|
|
125
125
|
ERROR2["TRADE_JOURNAL_ERROR"] = "TRADE_JOURNAL_ERROR";
|
|
126
126
|
ERROR2["TRADE_HISTORY_ERROR"] = "TRADE_HISTORY_ERROR";
|
|
127
127
|
ERROR2["ASSESSMENTS_ERROR"] = "ASSESSMENTS_ERROR";
|
|
128
|
+
ERROR2["RATE_LIMITED"] = "RATE_LIMITED";
|
|
129
|
+
ERROR2["WS_MANAGER_ERROR"] = "WS_MANAGER_ERROR";
|
|
130
|
+
ERROR2["STREAM_REQUIRES_CONNECT"] = "STREAM_REQUIRES_CONNECT";
|
|
128
131
|
return ERROR2;
|
|
129
132
|
})(ERROR || {});
|
|
130
133
|
var WS_MESSAGE = /* @__PURE__ */ ((WS_MESSAGE2) => {
|
|
@@ -163,7 +166,7 @@ var DxtradeError = class extends Error {
|
|
|
163
166
|
};
|
|
164
167
|
|
|
165
168
|
// src/domains/account/account.ts
|
|
166
|
-
var
|
|
169
|
+
var import_ws2 = __toESM(require("ws"));
|
|
167
170
|
|
|
168
171
|
// src/utils/cookies.ts
|
|
169
172
|
var Cookies = class {
|
|
@@ -216,7 +219,9 @@ async function retryRequest(config, retries = 3) {
|
|
|
216
219
|
} catch (error) {
|
|
217
220
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
218
221
|
console.warn(`[dxtrade-api] Attempt ${attempt} failed: ${message}`, config.url);
|
|
219
|
-
if ((0, import_axios.isAxiosError)(error) && error.response?.status === 429)
|
|
222
|
+
if ((0, import_axios.isAxiosError)(error) && error.response?.status === 429) {
|
|
223
|
+
throw new DxtradeError("RATE_LIMITED" /* RATE_LIMITED */, "Rate limited (429). Too many requests \u2014 try again later.");
|
|
224
|
+
}
|
|
220
225
|
if (attempt === retries) throw error;
|
|
221
226
|
await new Promise((res) => setTimeout(res, 1e3 * attempt));
|
|
222
227
|
}
|
|
@@ -259,13 +264,83 @@ function parseWsData(data) {
|
|
|
259
264
|
}
|
|
260
265
|
}
|
|
261
266
|
|
|
267
|
+
// src/utils/ws-manager.ts
|
|
268
|
+
var import_events = require("events");
|
|
269
|
+
var import_ws = __toESM(require("ws"));
|
|
270
|
+
var WsManager = class extends import_events.EventEmitter {
|
|
271
|
+
_ws = null;
|
|
272
|
+
_cache = /* @__PURE__ */ new Map();
|
|
273
|
+
connect(wsUrl, cookieStr, debug = false) {
|
|
274
|
+
return new Promise((resolve, reject) => {
|
|
275
|
+
const ws = new import_ws.default(wsUrl, { headers: { Cookie: cookieStr } });
|
|
276
|
+
ws.on("open", () => {
|
|
277
|
+
this._ws = ws;
|
|
278
|
+
resolve();
|
|
279
|
+
});
|
|
280
|
+
ws.on("message", (data) => {
|
|
281
|
+
const msg = parseWsData(data);
|
|
282
|
+
if (shouldLog(msg, debug)) debugLog(msg);
|
|
283
|
+
if (typeof msg === "string") return;
|
|
284
|
+
const payload = msg;
|
|
285
|
+
this._cache.set(payload.type, payload.body);
|
|
286
|
+
this.emit(payload.type, payload.body);
|
|
287
|
+
});
|
|
288
|
+
ws.on("error", (error) => {
|
|
289
|
+
if (!this._ws) {
|
|
290
|
+
return reject(error);
|
|
291
|
+
}
|
|
292
|
+
this.emit("error", error);
|
|
293
|
+
});
|
|
294
|
+
ws.on("close", () => {
|
|
295
|
+
this._ws = null;
|
|
296
|
+
this.emit("close");
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
waitFor(type, timeout = 3e4) {
|
|
301
|
+
const cached = this._cache.get(type);
|
|
302
|
+
if (cached !== void 0) {
|
|
303
|
+
return Promise.resolve(cached);
|
|
304
|
+
}
|
|
305
|
+
return new Promise((resolve, reject) => {
|
|
306
|
+
const timer = setTimeout(() => {
|
|
307
|
+
this.removeListener(type, onMessage);
|
|
308
|
+
reject(new Error(`WsManager: timed out waiting for ${type}`));
|
|
309
|
+
}, timeout);
|
|
310
|
+
const onMessage = (body) => {
|
|
311
|
+
clearTimeout(timer);
|
|
312
|
+
resolve(body);
|
|
313
|
+
};
|
|
314
|
+
this.once(type, onMessage);
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
getCached(type) {
|
|
318
|
+
return this._cache.get(type);
|
|
319
|
+
}
|
|
320
|
+
close() {
|
|
321
|
+
if (this._ws) {
|
|
322
|
+
this._ws.close();
|
|
323
|
+
this._ws = null;
|
|
324
|
+
}
|
|
325
|
+
this._cache.clear();
|
|
326
|
+
this.removeAllListeners();
|
|
327
|
+
}
|
|
328
|
+
get isConnected() {
|
|
329
|
+
return this._ws !== null && this._ws.readyState === import_ws.default.OPEN;
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
|
|
262
333
|
// src/domains/account/account.ts
|
|
263
334
|
async function getAccountMetrics(ctx, timeout = 3e4) {
|
|
264
335
|
ctx.ensureSession();
|
|
336
|
+
if (ctx.wsManager) {
|
|
337
|
+
const body = await ctx.wsManager.waitFor("ACCOUNT_METRICS" /* ACCOUNT_METRICS */, timeout);
|
|
338
|
+
return body.allMetrics;
|
|
339
|
+
}
|
|
265
340
|
const wsUrl = endpoints.websocket(ctx.broker, ctx.atmosphereId);
|
|
266
341
|
const cookieStr = Cookies.serialize(ctx.cookies);
|
|
267
342
|
return new Promise((resolve, reject) => {
|
|
268
|
-
const ws = new
|
|
343
|
+
const ws = new import_ws2.default(wsUrl, { headers: { Cookie: cookieStr } });
|
|
269
344
|
const timer = setTimeout(() => {
|
|
270
345
|
ws.close();
|
|
271
346
|
reject(new DxtradeError("ACCOUNT_METRICS_TIMEOUT" /* ACCOUNT_METRICS_TIMEOUT */, "Account metrics timed out"));
|
|
@@ -291,12 +366,11 @@ async function getAccountMetrics(ctx, timeout = 3e4) {
|
|
|
291
366
|
async function getTradeHistory(ctx, params) {
|
|
292
367
|
ctx.ensureSession();
|
|
293
368
|
try {
|
|
294
|
-
const cookieStr = Cookies.serialize(ctx.cookies);
|
|
295
369
|
const response = await retryRequest(
|
|
296
370
|
{
|
|
297
|
-
method: "
|
|
371
|
+
method: "POST",
|
|
298
372
|
url: endpoints.tradeHistory(ctx.broker, params),
|
|
299
|
-
headers:
|
|
373
|
+
headers: authHeaders(ctx.csrf, Cookies.serialize(ctx.cookies))
|
|
300
374
|
},
|
|
301
375
|
ctx.retries
|
|
302
376
|
);
|
|
@@ -368,13 +442,13 @@ async function getAssessments(ctx, params) {
|
|
|
368
442
|
}
|
|
369
443
|
|
|
370
444
|
// src/domains/instrument/instrument.ts
|
|
371
|
-
var
|
|
445
|
+
var import_ws3 = __toESM(require("ws"));
|
|
372
446
|
async function getInstruments(ctx, params = {}, timeout = 3e4) {
|
|
373
447
|
ctx.ensureSession();
|
|
374
448
|
const wsUrl = endpoints.websocket(ctx.broker, ctx.atmosphereId);
|
|
375
449
|
const cookieStr = Cookies.serialize(ctx.cookies);
|
|
376
450
|
return new Promise((resolve, reject) => {
|
|
377
|
-
const ws = new
|
|
451
|
+
const ws = new import_ws3.default(wsUrl, { headers: { Cookie: cookieStr } });
|
|
378
452
|
const timer = setTimeout(() => {
|
|
379
453
|
ws.close();
|
|
380
454
|
reject(new DxtradeError("INSTRUMENTS_TIMEOUT" /* INSTRUMENTS_TIMEOUT */, "Instruments request timed out"));
|
|
@@ -401,7 +475,7 @@ async function getInstruments(ctx, params = {}, timeout = 3e4) {
|
|
|
401
475
|
return true;
|
|
402
476
|
})
|
|
403
477
|
);
|
|
404
|
-
},
|
|
478
|
+
}, 200);
|
|
405
479
|
}
|
|
406
480
|
});
|
|
407
481
|
ws.on("error", (error) => {
|
|
@@ -413,7 +487,7 @@ async function getInstruments(ctx, params = {}, timeout = 3e4) {
|
|
|
413
487
|
}
|
|
414
488
|
|
|
415
489
|
// src/domains/ohlc/ohlc.ts
|
|
416
|
-
var
|
|
490
|
+
var import_ws4 = __toESM(require("ws"));
|
|
417
491
|
async function getOHLC(ctx, params, timeout = 3e4) {
|
|
418
492
|
ctx.ensureSession();
|
|
419
493
|
const { symbol, resolution = 60, range = 432e3, maxBars = 3500, priceField = "bid" } = params;
|
|
@@ -421,7 +495,7 @@ async function getOHLC(ctx, params, timeout = 3e4) {
|
|
|
421
495
|
const cookieStr = Cookies.serialize(ctx.cookies);
|
|
422
496
|
const headers = authHeaders(ctx.csrf, cookieStr);
|
|
423
497
|
return new Promise((resolve, reject) => {
|
|
424
|
-
const ws = new
|
|
498
|
+
const ws = new import_ws4.default(wsUrl, { headers: { Cookie: cookieStr } });
|
|
425
499
|
const bars = [];
|
|
426
500
|
let putsSent = false;
|
|
427
501
|
let initSettleTimer = null;
|
|
@@ -512,10 +586,10 @@ async function getOHLC(ctx, params, timeout = 3e4) {
|
|
|
512
586
|
|
|
513
587
|
// src/domains/order/order.ts
|
|
514
588
|
var import_crypto = __toESM(require("crypto"));
|
|
515
|
-
var
|
|
589
|
+
var import_ws6 = __toESM(require("ws"));
|
|
516
590
|
|
|
517
591
|
// src/domains/symbol/symbol.ts
|
|
518
|
-
var
|
|
592
|
+
var import_ws5 = __toESM(require("ws"));
|
|
519
593
|
async function getSymbolSuggestions(ctx, text) {
|
|
520
594
|
ctx.ensureSession();
|
|
521
595
|
try {
|
|
@@ -567,7 +641,7 @@ async function getSymbolLimits(ctx, timeout = 3e4) {
|
|
|
567
641
|
const wsUrl = endpoints.websocket(ctx.broker, ctx.atmosphereId);
|
|
568
642
|
const cookieStr = Cookies.serialize(ctx.cookies);
|
|
569
643
|
return new Promise((resolve, reject) => {
|
|
570
|
-
const ws = new
|
|
644
|
+
const ws = new import_ws5.default(wsUrl, { headers: { Cookie: cookieStr } });
|
|
571
645
|
const timer = setTimeout(() => {
|
|
572
646
|
ws.close();
|
|
573
647
|
reject(new DxtradeError("LIMITS_TIMEOUT" /* LIMITS_TIMEOUT */, "Symbol limits request timed out"));
|
|
@@ -587,7 +661,7 @@ async function getSymbolLimits(ctx, timeout = 3e4) {
|
|
|
587
661
|
clearTimeout(timer);
|
|
588
662
|
ws.close();
|
|
589
663
|
resolve(limits);
|
|
590
|
-
},
|
|
664
|
+
}, 200);
|
|
591
665
|
}
|
|
592
666
|
});
|
|
593
667
|
ws.on("error", (error) => {
|
|
@@ -600,7 +674,7 @@ async function getSymbolLimits(ctx, timeout = 3e4) {
|
|
|
600
674
|
|
|
601
675
|
// src/domains/order/order.ts
|
|
602
676
|
function createOrderListener(wsUrl, cookieStr, timeout = 3e4, debug = false) {
|
|
603
|
-
const ws = new
|
|
677
|
+
const ws = new import_ws6.default(wsUrl, { headers: { Cookie: cookieStr } });
|
|
604
678
|
let settled = false;
|
|
605
679
|
const ready = new Promise((resolve) => {
|
|
606
680
|
ws.on("open", resolve);
|
|
@@ -667,10 +741,13 @@ function createOrderListener(wsUrl, cookieStr, timeout = 3e4, debug = false) {
|
|
|
667
741
|
}
|
|
668
742
|
async function getOrders(ctx, timeout = 3e4) {
|
|
669
743
|
ctx.ensureSession();
|
|
744
|
+
if (ctx.wsManager) {
|
|
745
|
+
return ctx.wsManager.waitFor("ORDERS" /* ORDERS */, timeout);
|
|
746
|
+
}
|
|
670
747
|
const wsUrl = endpoints.websocket(ctx.broker, ctx.atmosphereId);
|
|
671
748
|
const cookieStr = Cookies.serialize(ctx.cookies);
|
|
672
749
|
return new Promise((resolve, reject) => {
|
|
673
|
-
const ws = new
|
|
750
|
+
const ws = new import_ws6.default(wsUrl, { headers: { Cookie: cookieStr } });
|
|
674
751
|
const timer = setTimeout(() => {
|
|
675
752
|
ws.close();
|
|
676
753
|
reject(new DxtradeError("ORDERS_TIMEOUT" /* ORDERS_TIMEOUT */, "Orders request timed out"));
|
|
@@ -814,13 +891,33 @@ async function submitOrder(ctx, params) {
|
|
|
814
891
|
}
|
|
815
892
|
|
|
816
893
|
// src/domains/position/position.ts
|
|
817
|
-
var
|
|
894
|
+
var import_ws7 = __toESM(require("ws"));
|
|
895
|
+
function streamPositions(ctx, callback) {
|
|
896
|
+
if (!ctx.wsManager) {
|
|
897
|
+
ctx.throwError(
|
|
898
|
+
"STREAM_REQUIRES_CONNECT" /* STREAM_REQUIRES_CONNECT */,
|
|
899
|
+
"Streaming requires a persistent WebSocket. Use connect() instead of auth()."
|
|
900
|
+
);
|
|
901
|
+
}
|
|
902
|
+
const listener = (body) => callback(body);
|
|
903
|
+
ctx.wsManager.on("POSITIONS" /* POSITIONS */, listener);
|
|
904
|
+
const cached = ctx.wsManager.getCached("POSITIONS" /* POSITIONS */);
|
|
905
|
+
if (cached !== void 0) {
|
|
906
|
+
callback(cached);
|
|
907
|
+
}
|
|
908
|
+
return () => {
|
|
909
|
+
ctx.wsManager?.removeListener("POSITIONS" /* POSITIONS */, listener);
|
|
910
|
+
};
|
|
911
|
+
}
|
|
818
912
|
async function getPositions(ctx) {
|
|
819
913
|
ctx.ensureSession();
|
|
914
|
+
if (ctx.wsManager) {
|
|
915
|
+
return ctx.wsManager.waitFor("POSITIONS" /* POSITIONS */);
|
|
916
|
+
}
|
|
820
917
|
const wsUrl = endpoints.websocket(ctx.broker, ctx.atmosphereId);
|
|
821
918
|
const cookieStr = Cookies.serialize(ctx.cookies);
|
|
822
919
|
return new Promise((resolve, reject) => {
|
|
823
|
-
const ws = new
|
|
920
|
+
const ws = new import_ws7.default(wsUrl, { headers: { Cookie: cookieStr } });
|
|
824
921
|
const timer = setTimeout(() => {
|
|
825
922
|
ws.close();
|
|
826
923
|
reject(new DxtradeError("ACCOUNT_POSITIONS_TIMEOUT" /* ACCOUNT_POSITIONS_TIMEOUT */, "Account positions timed out"));
|
|
@@ -844,10 +941,13 @@ async function getPositions(ctx) {
|
|
|
844
941
|
}
|
|
845
942
|
async function getPositionMetrics(ctx, timeout = 3e4) {
|
|
846
943
|
ctx.ensureSession();
|
|
944
|
+
if (ctx.wsManager) {
|
|
945
|
+
return ctx.wsManager.waitFor("POSITION_METRICS" /* POSITION_METRICS */, timeout);
|
|
946
|
+
}
|
|
847
947
|
const wsUrl = endpoints.websocket(ctx.broker, ctx.atmosphereId);
|
|
848
948
|
const cookieStr = Cookies.serialize(ctx.cookies);
|
|
849
949
|
return new Promise((resolve, reject) => {
|
|
850
|
-
const ws = new
|
|
950
|
+
const ws = new import_ws7.default(wsUrl, { headers: { Cookie: cookieStr } });
|
|
851
951
|
const timer = setTimeout(() => {
|
|
852
952
|
ws.close();
|
|
853
953
|
reject(new DxtradeError("POSITION_METRICS_TIMEOUT" /* POSITION_METRICS_TIMEOUT */, "Position metrics timed out"));
|
|
@@ -909,10 +1009,10 @@ async function closePosition(ctx, data) {
|
|
|
909
1009
|
}
|
|
910
1010
|
|
|
911
1011
|
// src/domains/session/session.ts
|
|
912
|
-
var
|
|
1012
|
+
var import_ws8 = __toESM(require("ws"));
|
|
913
1013
|
function waitForHandshake(wsUrl, cookieStr, timeout = 3e4, debug = false) {
|
|
914
1014
|
return new Promise((resolve, reject) => {
|
|
915
|
-
const ws = new
|
|
1015
|
+
const ws = new import_ws8.default(wsUrl, { headers: { Cookie: cookieStr } });
|
|
916
1016
|
let atmosphereId = null;
|
|
917
1017
|
const timer = setTimeout(() => {
|
|
918
1018
|
ws.close();
|
|
@@ -1012,7 +1112,7 @@ async function switchAccount(ctx, accountId) {
|
|
|
1012
1112
|
ctx.throwError("ACCOUNT_SWITCH_ERROR" /* ACCOUNT_SWITCH_ERROR */, `Error switching account: ${message}`);
|
|
1013
1113
|
}
|
|
1014
1114
|
}
|
|
1015
|
-
async function
|
|
1115
|
+
async function auth(ctx) {
|
|
1016
1116
|
await login(ctx);
|
|
1017
1117
|
await fetchCsrf(ctx);
|
|
1018
1118
|
if (ctx.debug) clearDebugLog();
|
|
@@ -1032,112 +1132,85 @@ async function connect(ctx) {
|
|
|
1032
1132
|
ctx.accountId = reconnect.accountId;
|
|
1033
1133
|
}
|
|
1034
1134
|
}
|
|
1135
|
+
async function connect(ctx) {
|
|
1136
|
+
await auth(ctx);
|
|
1137
|
+
const wsManager = new WsManager();
|
|
1138
|
+
const wsUrl = endpoints.websocket(ctx.broker, ctx.atmosphereId);
|
|
1139
|
+
const cookieStr = Cookies.serialize(ctx.cookies);
|
|
1140
|
+
await wsManager.connect(wsUrl, cookieStr, ctx.debug);
|
|
1141
|
+
ctx.wsManager = wsManager;
|
|
1142
|
+
}
|
|
1143
|
+
function disconnect(ctx) {
|
|
1144
|
+
if (ctx.wsManager) {
|
|
1145
|
+
ctx.wsManager.close();
|
|
1146
|
+
ctx.wsManager = null;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1035
1149
|
|
|
1036
1150
|
// src/client.ts
|
|
1037
|
-
var
|
|
1038
|
-
_ctx
|
|
1039
|
-
|
|
1040
|
-
const callbacks = config.callbacks ?? {};
|
|
1041
|
-
this._ctx = {
|
|
1042
|
-
config,
|
|
1043
|
-
callbacks,
|
|
1044
|
-
cookies: {},
|
|
1045
|
-
csrf: null,
|
|
1046
|
-
accountId: config.accountId ?? null,
|
|
1047
|
-
atmosphereId: null,
|
|
1048
|
-
broker: config.broker,
|
|
1049
|
-
retries: config.retries ?? 3,
|
|
1050
|
-
debug: config.debug ?? false,
|
|
1051
|
-
ensureSession() {
|
|
1052
|
-
if (!this.csrf) {
|
|
1053
|
-
throw new DxtradeError(
|
|
1054
|
-
"NO_SESSION" /* NO_SESSION */,
|
|
1055
|
-
"No active session. Call login() and fetchCsrf() or connect() first."
|
|
1056
|
-
);
|
|
1057
|
-
}
|
|
1058
|
-
},
|
|
1059
|
-
throwError(code, message) {
|
|
1060
|
-
const error = new DxtradeError(code, message);
|
|
1061
|
-
callbacks.onError?.(error);
|
|
1062
|
-
throw error;
|
|
1063
|
-
}
|
|
1064
|
-
};
|
|
1151
|
+
var PositionsDomain = class {
|
|
1152
|
+
constructor(_ctx) {
|
|
1153
|
+
this._ctx = _ctx;
|
|
1065
1154
|
}
|
|
1066
|
-
/**
|
|
1067
|
-
|
|
1068
|
-
return
|
|
1155
|
+
/** Get all open positions via WebSocket. */
|
|
1156
|
+
get() {
|
|
1157
|
+
return getPositions(this._ctx);
|
|
1069
1158
|
}
|
|
1070
|
-
/**
|
|
1071
|
-
|
|
1072
|
-
return
|
|
1159
|
+
/** Close a position. Supports partial closes by specifying a quantity smaller than the full position size. */
|
|
1160
|
+
close(params) {
|
|
1161
|
+
return closePosition(this._ctx, params);
|
|
1073
1162
|
}
|
|
1074
|
-
/**
|
|
1075
|
-
|
|
1076
|
-
return
|
|
1163
|
+
/** Close all open positions with market orders. */
|
|
1164
|
+
closeAll() {
|
|
1165
|
+
return closeAllPositions(this._ctx);
|
|
1077
1166
|
}
|
|
1078
|
-
/**
|
|
1079
|
-
|
|
1080
|
-
return
|
|
1167
|
+
/** Get position-level P&L metrics via WebSocket. */
|
|
1168
|
+
metrics() {
|
|
1169
|
+
return getPositionMetrics(this._ctx);
|
|
1081
1170
|
}
|
|
1082
|
-
/**
|
|
1083
|
-
|
|
1084
|
-
return
|
|
1171
|
+
/** Stream real-time position updates. Requires connect(). Returns unsubscribe function. */
|
|
1172
|
+
stream(callback) {
|
|
1173
|
+
return streamPositions(this._ctx, callback);
|
|
1085
1174
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1175
|
+
};
|
|
1176
|
+
var OrdersDomain = class {
|
|
1177
|
+
constructor(_ctx) {
|
|
1178
|
+
this._ctx = _ctx;
|
|
1089
1179
|
}
|
|
1090
|
-
/** Get
|
|
1091
|
-
|
|
1092
|
-
return
|
|
1180
|
+
/** Get all pending/open orders via WebSocket. */
|
|
1181
|
+
get() {
|
|
1182
|
+
return getOrders(this._ctx);
|
|
1093
1183
|
}
|
|
1094
1184
|
/**
|
|
1095
1185
|
* Submit a trading order and wait for WebSocket confirmation.
|
|
1096
1186
|
* Supports market, limit, and stop orders with optional stop loss and take profit.
|
|
1097
1187
|
*/
|
|
1098
|
-
|
|
1188
|
+
submit(params) {
|
|
1099
1189
|
return submitOrder(this._ctx, params);
|
|
1100
1190
|
}
|
|
1101
|
-
/** Get all pending/open orders via WebSocket. */
|
|
1102
|
-
async getOrders() {
|
|
1103
|
-
return getOrders(this._ctx);
|
|
1104
|
-
}
|
|
1105
1191
|
/** Cancel a single pending order by its order chain ID. */
|
|
1106
|
-
|
|
1192
|
+
cancel(orderChainId) {
|
|
1107
1193
|
return cancelOrder(this._ctx, orderChainId);
|
|
1108
1194
|
}
|
|
1109
1195
|
/** Cancel all pending orders. */
|
|
1110
|
-
|
|
1196
|
+
cancelAll() {
|
|
1111
1197
|
return cancelAllOrders(this._ctx);
|
|
1112
1198
|
}
|
|
1199
|
+
};
|
|
1200
|
+
var AccountDomain = class {
|
|
1201
|
+
constructor(_ctx) {
|
|
1202
|
+
this._ctx = _ctx;
|
|
1203
|
+
}
|
|
1113
1204
|
/** Get account metrics including equity, balance, margin, and open P&L. */
|
|
1114
|
-
|
|
1205
|
+
metrics() {
|
|
1115
1206
|
return getAccountMetrics(this._ctx);
|
|
1116
1207
|
}
|
|
1117
|
-
/** Get all open positions via WebSocket. */
|
|
1118
|
-
async getPositions() {
|
|
1119
|
-
return getPositions(this._ctx);
|
|
1120
|
-
}
|
|
1121
|
-
/**
|
|
1122
|
-
* Close a position. Supports partial closes by specifying a quantity smaller than the full position size.
|
|
1123
|
-
*/
|
|
1124
|
-
async closePosition(position) {
|
|
1125
|
-
return closePosition(this._ctx, position);
|
|
1126
|
-
}
|
|
1127
|
-
/** Close all open positions with market orders. */
|
|
1128
|
-
async closeAllPositions() {
|
|
1129
|
-
return closeAllPositions(this._ctx);
|
|
1130
|
-
}
|
|
1131
|
-
/** Get position-level P&L metrics via WebSocket. */
|
|
1132
|
-
async getPositionMetrics() {
|
|
1133
|
-
return getPositionMetrics(this._ctx);
|
|
1134
|
-
}
|
|
1135
1208
|
/**
|
|
1136
1209
|
* Fetch trade journal entries for a date range.
|
|
1137
1210
|
* @param params.from - Start timestamp (Unix ms)
|
|
1138
1211
|
* @param params.to - End timestamp (Unix ms)
|
|
1139
1212
|
*/
|
|
1140
|
-
|
|
1213
|
+
tradeJournal(params) {
|
|
1141
1214
|
return getTradeJournal(this._ctx, params);
|
|
1142
1215
|
}
|
|
1143
1216
|
/**
|
|
@@ -1145,16 +1218,39 @@ var DxtradeClient = class {
|
|
|
1145
1218
|
* @param params.from - Start timestamp (Unix ms)
|
|
1146
1219
|
* @param params.to - End timestamp (Unix ms)
|
|
1147
1220
|
*/
|
|
1148
|
-
|
|
1221
|
+
tradeHistory(params) {
|
|
1149
1222
|
return getTradeHistory(this._ctx, params);
|
|
1150
1223
|
}
|
|
1224
|
+
};
|
|
1225
|
+
var SymbolsDomain = class {
|
|
1226
|
+
constructor(_ctx) {
|
|
1227
|
+
this._ctx = _ctx;
|
|
1228
|
+
}
|
|
1229
|
+
/** Search for symbols matching the given text (e.g. "EURUSD", "BTC"). */
|
|
1230
|
+
search(text) {
|
|
1231
|
+
return getSymbolSuggestions(this._ctx, text);
|
|
1232
|
+
}
|
|
1233
|
+
/** Get detailed instrument info for a symbol, including volume limits and lot size. */
|
|
1234
|
+
info(symbol) {
|
|
1235
|
+
return getSymbolInfo(this._ctx, symbol);
|
|
1236
|
+
}
|
|
1237
|
+
/** Get order size limits and stop/limit distances for all symbols. */
|
|
1238
|
+
limits() {
|
|
1239
|
+
return getSymbolLimits(this._ctx);
|
|
1240
|
+
}
|
|
1241
|
+
};
|
|
1242
|
+
var InstrumentsDomain = class {
|
|
1243
|
+
constructor(_ctx) {
|
|
1244
|
+
this._ctx = _ctx;
|
|
1245
|
+
}
|
|
1151
1246
|
/** Get all available instruments, optionally filtered by partial match (e.g. `{ type: "FOREX" }`). */
|
|
1152
|
-
|
|
1247
|
+
get(params = {}) {
|
|
1153
1248
|
return getInstruments(this._ctx, params);
|
|
1154
1249
|
}
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1250
|
+
};
|
|
1251
|
+
var OhlcDomain = class {
|
|
1252
|
+
constructor(_ctx) {
|
|
1253
|
+
this._ctx = _ctx;
|
|
1158
1254
|
}
|
|
1159
1255
|
/**
|
|
1160
1256
|
* Fetch OHLC price bars for a symbol.
|
|
@@ -1164,10 +1260,92 @@ var DxtradeClient = class {
|
|
|
1164
1260
|
* @param params.maxBars - Maximum bars to return (default: 3500)
|
|
1165
1261
|
* @param params.priceField - "bid" or "ask" (default: "bid")
|
|
1166
1262
|
*/
|
|
1167
|
-
|
|
1263
|
+
get(params) {
|
|
1168
1264
|
return getOHLC(this._ctx, params);
|
|
1169
1265
|
}
|
|
1170
1266
|
};
|
|
1267
|
+
var AssessmentsDomain = class {
|
|
1268
|
+
constructor(_ctx) {
|
|
1269
|
+
this._ctx = _ctx;
|
|
1270
|
+
}
|
|
1271
|
+
/** Fetch PnL assessments for an instrument within a date range. */
|
|
1272
|
+
get(params) {
|
|
1273
|
+
return getAssessments(this._ctx, params);
|
|
1274
|
+
}
|
|
1275
|
+
};
|
|
1276
|
+
var DxtradeClient = class {
|
|
1277
|
+
_ctx;
|
|
1278
|
+
/** Position operations: get, close, metrics, streaming. */
|
|
1279
|
+
positions;
|
|
1280
|
+
/** Order operations: get, submit, cancel. */
|
|
1281
|
+
orders;
|
|
1282
|
+
/** Account operations: metrics, trade journal, trade history. */
|
|
1283
|
+
account;
|
|
1284
|
+
/** Symbol operations: search, info, limits. */
|
|
1285
|
+
symbols;
|
|
1286
|
+
/** Instrument operations: get (with optional filtering). */
|
|
1287
|
+
instruments;
|
|
1288
|
+
/** OHLC price bar operations: get. */
|
|
1289
|
+
ohlc;
|
|
1290
|
+
/** PnL assessment operations: get. */
|
|
1291
|
+
assessments;
|
|
1292
|
+
constructor(config) {
|
|
1293
|
+
const callbacks = config.callbacks ?? {};
|
|
1294
|
+
this._ctx = {
|
|
1295
|
+
config,
|
|
1296
|
+
callbacks,
|
|
1297
|
+
cookies: {},
|
|
1298
|
+
csrf: null,
|
|
1299
|
+
accountId: config.accountId ?? null,
|
|
1300
|
+
atmosphereId: null,
|
|
1301
|
+
wsManager: null,
|
|
1302
|
+
broker: config.broker,
|
|
1303
|
+
retries: config.retries ?? 3,
|
|
1304
|
+
debug: config.debug ?? false,
|
|
1305
|
+
ensureSession() {
|
|
1306
|
+
if (!this.csrf) {
|
|
1307
|
+
throw new DxtradeError("NO_SESSION" /* NO_SESSION */, "No active session. Call auth() or connect() first.");
|
|
1308
|
+
}
|
|
1309
|
+
},
|
|
1310
|
+
throwError(code, message) {
|
|
1311
|
+
const error = new DxtradeError(code, message);
|
|
1312
|
+
callbacks.onError?.(error);
|
|
1313
|
+
throw error;
|
|
1314
|
+
}
|
|
1315
|
+
};
|
|
1316
|
+
this.positions = new PositionsDomain(this._ctx);
|
|
1317
|
+
this.orders = new OrdersDomain(this._ctx);
|
|
1318
|
+
this.account = new AccountDomain(this._ctx);
|
|
1319
|
+
this.symbols = new SymbolsDomain(this._ctx);
|
|
1320
|
+
this.instruments = new InstrumentsDomain(this._ctx);
|
|
1321
|
+
this.ohlc = new OhlcDomain(this._ctx);
|
|
1322
|
+
this.assessments = new AssessmentsDomain(this._ctx);
|
|
1323
|
+
}
|
|
1324
|
+
/** Authenticate with the broker using username and password. */
|
|
1325
|
+
async login() {
|
|
1326
|
+
return login(this._ctx);
|
|
1327
|
+
}
|
|
1328
|
+
/** Fetch the CSRF token required for authenticated requests. */
|
|
1329
|
+
async fetchCsrf() {
|
|
1330
|
+
return fetchCsrf(this._ctx);
|
|
1331
|
+
}
|
|
1332
|
+
/** Switch to a specific trading account by ID. */
|
|
1333
|
+
async switchAccount(accountId) {
|
|
1334
|
+
return switchAccount(this._ctx, accountId);
|
|
1335
|
+
}
|
|
1336
|
+
/** Authenticate and establish a session: login, fetch CSRF, WebSocket handshake, and optional account switch. */
|
|
1337
|
+
async auth() {
|
|
1338
|
+
return auth(this._ctx);
|
|
1339
|
+
}
|
|
1340
|
+
/** Connect to the broker with a persistent WebSocket: auth + persistent WS for data reuse and streaming. */
|
|
1341
|
+
async connect() {
|
|
1342
|
+
return connect(this._ctx);
|
|
1343
|
+
}
|
|
1344
|
+
/** Close the persistent WebSocket connection. */
|
|
1345
|
+
disconnect() {
|
|
1346
|
+
return disconnect(this._ctx);
|
|
1347
|
+
}
|
|
1348
|
+
};
|
|
1171
1349
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1172
1350
|
0 && (module.exports = {
|
|
1173
1351
|
ACTION,
|