@pipsend/sdk 0.1.0 → 0.1.2
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 +259 -32
- package/dist/index.d.mts +328 -29
- package/dist/index.d.ts +328 -29
- package/dist/index.js +313 -74
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +313 -74
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -7,11 +7,30 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
7
7
|
|
|
8
8
|
// src/types/index.ts
|
|
9
9
|
var PipsendError = class extends Error {
|
|
10
|
-
constructor(message, code, statusCode) {
|
|
10
|
+
constructor(message, code, statusCode, errors, response) {
|
|
11
11
|
super(message);
|
|
12
12
|
this.code = code;
|
|
13
13
|
this.statusCode = statusCode;
|
|
14
14
|
this.name = "PipsendError";
|
|
15
|
+
this.errors = errors;
|
|
16
|
+
this.response = response;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get formatted error message with validation details
|
|
20
|
+
*/
|
|
21
|
+
getDetailedMessage() {
|
|
22
|
+
if (!this.errors || this.errors.length === 0) {
|
|
23
|
+
return this.message;
|
|
24
|
+
}
|
|
25
|
+
const errorDetails = this.errors.map((err) => ` - ${err.field}: ${err.message}`).join("\n");
|
|
26
|
+
return `${this.message}
|
|
27
|
+
${errorDetails}`;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Check if this is a validation error
|
|
31
|
+
*/
|
|
32
|
+
isValidationError() {
|
|
33
|
+
return this.statusCode === 422 || this.code === "VALIDATION_ERROR";
|
|
15
34
|
}
|
|
16
35
|
};
|
|
17
36
|
var AuthenticationError = class extends PipsendError {
|
|
@@ -66,17 +85,35 @@ var AuthManager = class {
|
|
|
66
85
|
}
|
|
67
86
|
/**
|
|
68
87
|
* Performs authentication with the server
|
|
69
|
-
* TODO: Implement real API call when available
|
|
70
88
|
*/
|
|
71
89
|
async authenticate() {
|
|
90
|
+
if (!this.config.login || !this.config.password) {
|
|
91
|
+
throw new AuthenticationError(
|
|
92
|
+
"Login and password are required for authentication. Please provide them in the config."
|
|
93
|
+
);
|
|
94
|
+
}
|
|
72
95
|
try {
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
96
|
+
const response = await fetch(`${this.config.server}/api/v1/auth/login`, {
|
|
97
|
+
method: "POST",
|
|
98
|
+
headers: { "Content-Type": "application/json" },
|
|
99
|
+
body: JSON.stringify({
|
|
100
|
+
login: this.config.login,
|
|
101
|
+
password: this.config.password
|
|
102
|
+
})
|
|
103
|
+
});
|
|
104
|
+
if (!response.ok) {
|
|
105
|
+
const errorData = await response.json().catch(() => ({}));
|
|
106
|
+
throw new AuthenticationError(
|
|
107
|
+
errorData.message || `Authentication failed: ${response.status} ${response.statusText}`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
const data = await response.json();
|
|
111
|
+
this.setTokenInfo(data);
|
|
112
|
+
console.log("\u2705 Authentication successful");
|
|
113
|
+
console.log(` User: ${data.user.first_name} ${data.user.last_name} (${data.user.email})`);
|
|
114
|
+
console.log(` Login: ${data.user.login}`);
|
|
115
|
+
console.log(` Balance: $${data.user.balance.toFixed(2)}`);
|
|
116
|
+
console.log(` Logged with: ${data.logged_with}`);
|
|
80
117
|
} catch (error) {
|
|
81
118
|
if (error instanceof AuthenticationError) {
|
|
82
119
|
throw error;
|
|
@@ -87,11 +124,45 @@ var AuthManager = class {
|
|
|
87
124
|
}
|
|
88
125
|
}
|
|
89
126
|
/**
|
|
90
|
-
*
|
|
127
|
+
* Refreshes the access token using the refresh token
|
|
91
128
|
*/
|
|
92
129
|
async refreshToken() {
|
|
93
|
-
this.tokenInfo
|
|
94
|
-
|
|
130
|
+
if (!this.tokenInfo?.refreshToken) {
|
|
131
|
+
console.log("\u26A0\uFE0F No refresh token available, performing full authentication");
|
|
132
|
+
this.tokenInfo = void 0;
|
|
133
|
+
await this.authenticate();
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
const response = await fetch(`${this.config.server}/api/v1/auth/refresh`, {
|
|
138
|
+
method: "POST",
|
|
139
|
+
headers: { "Content-Type": "application/json" },
|
|
140
|
+
body: JSON.stringify({
|
|
141
|
+
refresh_token: this.tokenInfo.refreshToken
|
|
142
|
+
})
|
|
143
|
+
});
|
|
144
|
+
if (!response.ok) {
|
|
145
|
+
console.log("\u26A0\uFE0F Refresh token failed, performing full authentication");
|
|
146
|
+
this.tokenInfo = void 0;
|
|
147
|
+
await this.authenticate();
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const data = await response.json();
|
|
151
|
+
const now = /* @__PURE__ */ new Date();
|
|
152
|
+
const expiresAt = new Date(now.getTime() + data.expires_in * 1e3);
|
|
153
|
+
this.tokenInfo = {
|
|
154
|
+
token: data.access_token,
|
|
155
|
+
refreshToken: this.tokenInfo.refreshToken,
|
|
156
|
+
// Keep the same refresh token
|
|
157
|
+
issuedAt: now,
|
|
158
|
+
expiresAt
|
|
159
|
+
};
|
|
160
|
+
console.log("\u2705 Token refreshed successfully");
|
|
161
|
+
} catch (error) {
|
|
162
|
+
console.error("\u274C Error refreshing token:", error);
|
|
163
|
+
this.tokenInfo = void 0;
|
|
164
|
+
await this.authenticate();
|
|
165
|
+
}
|
|
95
166
|
}
|
|
96
167
|
/**
|
|
97
168
|
* Clears the current token
|
|
@@ -113,9 +184,10 @@ var AuthManager = class {
|
|
|
113
184
|
*/
|
|
114
185
|
setTokenInfo(response) {
|
|
115
186
|
const now = /* @__PURE__ */ new Date();
|
|
116
|
-
const expiresAt = new Date(now.getTime() + response.
|
|
187
|
+
const expiresAt = new Date(now.getTime() + response.expires_in * 1e3);
|
|
117
188
|
this.tokenInfo = {
|
|
118
|
-
token: response.
|
|
189
|
+
token: response.access_token,
|
|
190
|
+
refreshToken: response.refresh_token,
|
|
119
191
|
issuedAt: now,
|
|
120
192
|
expiresAt
|
|
121
193
|
};
|
|
@@ -146,8 +218,9 @@ var WebSocketManager = class {
|
|
|
146
218
|
console.log("\u26A0\uFE0F WebSocket reconnection in progress");
|
|
147
219
|
return;
|
|
148
220
|
}
|
|
149
|
-
const wsUrl = this.buildWebSocketUrl();
|
|
150
221
|
const token = await this.authManager.ensureAuthenticated();
|
|
222
|
+
const baseWsUrl = this.buildWebSocketUrl();
|
|
223
|
+
const wsUrl = `${baseWsUrl}${baseWsUrl.includes("?") ? "&" : "?"}token=${encodeURIComponent(token)}`;
|
|
151
224
|
return new Promise((resolve, reject) => {
|
|
152
225
|
try {
|
|
153
226
|
const WS = this.getWebSocketConstructor();
|
|
@@ -157,11 +230,6 @@ var WebSocketManager = class {
|
|
|
157
230
|
this.isConnected = true;
|
|
158
231
|
this.isReconnecting = false;
|
|
159
232
|
this.reconnectAttempts = 0;
|
|
160
|
-
this.send({
|
|
161
|
-
type: "auth",
|
|
162
|
-
payload: { token },
|
|
163
|
-
timestamp: Date.now()
|
|
164
|
-
});
|
|
165
233
|
this.emit("connected", { timestamp: Date.now() });
|
|
166
234
|
if (this.subscribedChannels.length > 0) {
|
|
167
235
|
console.log("\u{1F504} Resubscribing to channels:", this.subscribedChannels);
|
|
@@ -204,24 +272,22 @@ var WebSocketManager = class {
|
|
|
204
272
|
});
|
|
205
273
|
}
|
|
206
274
|
/**
|
|
207
|
-
* Subscribes to channels
|
|
208
|
-
* TODO: Adjust message format according to real WebSocket API
|
|
275
|
+
* Subscribes to WebSocket channels
|
|
209
276
|
*/
|
|
210
277
|
subscribe(channels) {
|
|
211
278
|
if (!this.isConnected) {
|
|
212
279
|
throw new WebSocketError("WebSocket not connected. Call connect() first.");
|
|
213
280
|
}
|
|
214
281
|
this.subscribedChannels = [.../* @__PURE__ */ new Set([...this.subscribedChannels, ...channels])];
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
282
|
+
const message = {
|
|
283
|
+
action: "subscribe",
|
|
284
|
+
channels
|
|
285
|
+
};
|
|
286
|
+
this.sendAction(message);
|
|
220
287
|
console.log("\u{1F4E1} Subscribed to channels:", channels);
|
|
221
288
|
}
|
|
222
289
|
/**
|
|
223
|
-
* Unsubscribes from channels
|
|
224
|
-
* TODO: Adjust message format according to real WebSocket API
|
|
290
|
+
* Unsubscribes from WebSocket channels
|
|
225
291
|
*/
|
|
226
292
|
unsubscribe(channels) {
|
|
227
293
|
if (!this.isConnected) {
|
|
@@ -231,11 +297,11 @@ var WebSocketManager = class {
|
|
|
231
297
|
this.subscribedChannels = this.subscribedChannels.filter(
|
|
232
298
|
(ch) => !channels.includes(ch)
|
|
233
299
|
);
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
300
|
+
const message = {
|
|
301
|
+
action: "unsubscribe",
|
|
302
|
+
channels
|
|
303
|
+
};
|
|
304
|
+
this.sendAction(message);
|
|
239
305
|
console.log("\u{1F4E1} Unsubscribed from channels:", channels);
|
|
240
306
|
}
|
|
241
307
|
/**
|
|
@@ -292,7 +358,7 @@ var WebSocketManager = class {
|
|
|
292
358
|
try {
|
|
293
359
|
const url = new URL(this.config.server);
|
|
294
360
|
url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
|
|
295
|
-
const wsPath = this.config.websocket?.path || "/ws";
|
|
361
|
+
const wsPath = this.config.websocket?.path || "/api/v1/ws";
|
|
296
362
|
url.pathname = wsPath;
|
|
297
363
|
return url.toString();
|
|
298
364
|
} catch (error) {
|
|
@@ -315,11 +381,11 @@ var WebSocketManager = class {
|
|
|
315
381
|
}
|
|
316
382
|
}
|
|
317
383
|
/**
|
|
318
|
-
* Sends
|
|
384
|
+
* Sends an action message through WebSocket
|
|
319
385
|
*/
|
|
320
|
-
|
|
386
|
+
sendAction(message) {
|
|
321
387
|
if (!this.ws || !this.isConnected) {
|
|
322
|
-
console.warn("\u26A0\uFE0F WebSocket not ready, message not sent:", message.
|
|
388
|
+
console.warn("\u26A0\uFE0F WebSocket not ready, message not sent:", message.action);
|
|
323
389
|
return;
|
|
324
390
|
}
|
|
325
391
|
try {
|
|
@@ -330,21 +396,99 @@ var WebSocketManager = class {
|
|
|
330
396
|
}
|
|
331
397
|
}
|
|
332
398
|
/**
|
|
333
|
-
*
|
|
334
|
-
* TODO: Adjust message handling according to real WebSocket API
|
|
399
|
+
* Sends a ping message (for heartbeat)
|
|
335
400
|
*/
|
|
336
|
-
|
|
337
|
-
if (
|
|
338
|
-
console.log("\u2705 WebSocket authenticated");
|
|
339
|
-
this.emit("authenticated", data.payload || {});
|
|
401
|
+
sendPing() {
|
|
402
|
+
if (!this.ws || !this.isConnected) {
|
|
340
403
|
return;
|
|
341
404
|
}
|
|
342
|
-
|
|
343
|
-
|
|
405
|
+
try {
|
|
406
|
+
this.ws.send(JSON.stringify({ action: "ping" }));
|
|
407
|
+
} catch (error) {
|
|
408
|
+
console.error("\u274C Failed to send ping:", error);
|
|
344
409
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Handles incoming WebSocket messages
|
|
413
|
+
*/
|
|
414
|
+
handleMessage(message) {
|
|
415
|
+
switch (message.op) {
|
|
416
|
+
case "connected":
|
|
417
|
+
this.handleConnected(message);
|
|
418
|
+
break;
|
|
419
|
+
case "subscription_success":
|
|
420
|
+
this.handleSubscriptionSuccess(message);
|
|
421
|
+
break;
|
|
422
|
+
case "unsubscription_success":
|
|
423
|
+
this.handleUnsubscriptionSuccess(message);
|
|
424
|
+
break;
|
|
425
|
+
case "push":
|
|
426
|
+
this.handlePushEvent(message);
|
|
427
|
+
break;
|
|
428
|
+
case "error":
|
|
429
|
+
this.handleError(message);
|
|
430
|
+
break;
|
|
431
|
+
default:
|
|
432
|
+
console.warn(message.op);
|
|
433
|
+
}
|
|
434
|
+
this.emit("*", message);
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Handles connected message from server
|
|
438
|
+
*/
|
|
439
|
+
handleConnected(message) {
|
|
440
|
+
console.log("\u2705 WebSocket connected:", message.data.message);
|
|
441
|
+
console.log(" Available channels:", message.data.available_channels);
|
|
442
|
+
this.emit("connected", message.data);
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Handles subscription success
|
|
446
|
+
*/
|
|
447
|
+
handleSubscriptionSuccess(message) {
|
|
448
|
+
console.log("\u2705 Subscription successful:", message.data.subscribed);
|
|
449
|
+
this.emit("subscription_success", message.data);
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Handles unsubscription success
|
|
453
|
+
*/
|
|
454
|
+
handleUnsubscriptionSuccess(message) {
|
|
455
|
+
console.log("\u2705 Unsubscription successful:", message.data.unsubscribed);
|
|
456
|
+
this.emit("unsubscription_success", message.data);
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Handles push events (actual data events)
|
|
460
|
+
*/
|
|
461
|
+
handlePushEvent(message) {
|
|
462
|
+
const eventData = message.data;
|
|
463
|
+
const eventType = eventData.type;
|
|
464
|
+
switch (eventType) {
|
|
465
|
+
case "position.opened":
|
|
466
|
+
this.emit("position:opened", eventData);
|
|
467
|
+
break;
|
|
468
|
+
case "position.closed":
|
|
469
|
+
case "position.partially_closed":
|
|
470
|
+
this.emit("position:closed", eventData);
|
|
471
|
+
break;
|
|
472
|
+
case "position.updated":
|
|
473
|
+
this.emit("position:updated", eventData);
|
|
474
|
+
break;
|
|
475
|
+
default:
|
|
476
|
+
if (message.topic?.startsWith("balance:")) {
|
|
477
|
+
this.emit("balance:updated", eventData);
|
|
478
|
+
} else {
|
|
479
|
+
console.warn("Unknown event type:", eventType);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Handles error messages from server
|
|
485
|
+
*/
|
|
486
|
+
handleError(message) {
|
|
487
|
+
console.error("\u274C WebSocket error:", message.data.message);
|
|
488
|
+
if (message.data.error) {
|
|
489
|
+
console.error(" Error details:", message.data.error);
|
|
490
|
+
}
|
|
491
|
+
this.emit("error", message.data);
|
|
348
492
|
}
|
|
349
493
|
/**
|
|
350
494
|
* Emits an event to all registered listeners
|
|
@@ -395,10 +539,7 @@ var WebSocketManager = class {
|
|
|
395
539
|
const interval = this.config.websocket?.heartbeatInterval || 3e4;
|
|
396
540
|
this.heartbeatTimer = setInterval(() => {
|
|
397
541
|
if (this.isConnected) {
|
|
398
|
-
this.
|
|
399
|
-
type: "ping",
|
|
400
|
-
timestamp: Date.now()
|
|
401
|
-
});
|
|
542
|
+
this.sendPing();
|
|
402
543
|
}
|
|
403
544
|
}, interval);
|
|
404
545
|
}
|
|
@@ -415,28 +556,59 @@ var WebSocketManager = class {
|
|
|
415
556
|
|
|
416
557
|
// src/api/http-client.ts
|
|
417
558
|
var HttpClient = class {
|
|
418
|
-
constructor(baseUrl) {
|
|
559
|
+
constructor(baseUrl, authManager) {
|
|
419
560
|
this.baseUrl = baseUrl;
|
|
561
|
+
this.authManager = authManager;
|
|
420
562
|
}
|
|
421
563
|
/**
|
|
422
564
|
* Makes an HTTP request
|
|
423
565
|
*/
|
|
424
|
-
async request(endpoint, options = {}) {
|
|
566
|
+
async request(endpoint, options = {}, retryOn401 = true) {
|
|
425
567
|
const url = `${this.baseUrl}${endpoint}`;
|
|
426
568
|
try {
|
|
569
|
+
const headers = {
|
|
570
|
+
"Content-Type": "application/json",
|
|
571
|
+
...options.headers || {}
|
|
572
|
+
};
|
|
573
|
+
if (this.authManager) {
|
|
574
|
+
const token = await this.authManager.ensureAuthenticated();
|
|
575
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
576
|
+
}
|
|
427
577
|
const response = await fetch(url, {
|
|
428
578
|
...options,
|
|
429
|
-
headers
|
|
430
|
-
"Content-Type": "application/json",
|
|
431
|
-
...options.headers
|
|
432
|
-
}
|
|
579
|
+
headers
|
|
433
580
|
});
|
|
581
|
+
if (response.status === 401 && this.authManager && retryOn401) {
|
|
582
|
+
console.log("\u26A0\uFE0F Received 401, attempting to refresh token...");
|
|
583
|
+
await this.authManager.refreshToken();
|
|
584
|
+
return this.request(endpoint, options, false);
|
|
585
|
+
}
|
|
434
586
|
if (!response.ok) {
|
|
435
587
|
const errorText = await response.text();
|
|
588
|
+
let errorMessage = `HTTP ${response.status}: ${errorText || response.statusText}`;
|
|
589
|
+
let errorCode = "HTTP_ERROR";
|
|
590
|
+
let validationErrors;
|
|
591
|
+
let errorResponse;
|
|
592
|
+
try {
|
|
593
|
+
const errorJson = JSON.parse(errorText);
|
|
594
|
+
errorResponse = errorJson;
|
|
595
|
+
if (errorJson.message) {
|
|
596
|
+
errorMessage = errorJson.message;
|
|
597
|
+
}
|
|
598
|
+
if (errorJson.status_code) {
|
|
599
|
+
errorCode = errorJson.status_code;
|
|
600
|
+
}
|
|
601
|
+
if (errorJson.errors && Array.isArray(errorJson.errors)) {
|
|
602
|
+
validationErrors = errorJson.errors;
|
|
603
|
+
}
|
|
604
|
+
} catch {
|
|
605
|
+
}
|
|
436
606
|
throw new PipsendError(
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
response.status
|
|
607
|
+
errorMessage,
|
|
608
|
+
errorCode,
|
|
609
|
+
response.status,
|
|
610
|
+
validationErrors,
|
|
611
|
+
errorResponse
|
|
440
612
|
);
|
|
441
613
|
}
|
|
442
614
|
const text = await response.text();
|
|
@@ -500,6 +672,12 @@ var AccountsAPI = class {
|
|
|
500
672
|
constructor(http) {
|
|
501
673
|
this.http = http;
|
|
502
674
|
}
|
|
675
|
+
/**
|
|
676
|
+
* Create a new trading account
|
|
677
|
+
*/
|
|
678
|
+
async create(request) {
|
|
679
|
+
return this.http.post("/api/v1/accounts", request);
|
|
680
|
+
}
|
|
503
681
|
/**
|
|
504
682
|
* List all accounts with optional filters and pagination
|
|
505
683
|
*/
|
|
@@ -512,6 +690,12 @@ var AccountsAPI = class {
|
|
|
512
690
|
async getLogins() {
|
|
513
691
|
return this.http.get("/api/v1/accounts/logins");
|
|
514
692
|
}
|
|
693
|
+
/**
|
|
694
|
+
* Get account status/metrics (balance, equity, credit, margin)
|
|
695
|
+
*/
|
|
696
|
+
async getStatus(login) {
|
|
697
|
+
return this.http.get(`/api/v1/accounts/${login}/status`);
|
|
698
|
+
}
|
|
515
699
|
/**
|
|
516
700
|
* Get account statistics with optional filters
|
|
517
701
|
*/
|
|
@@ -542,6 +726,20 @@ var AccountsAPI = class {
|
|
|
542
726
|
async unarchive(login) {
|
|
543
727
|
return this.http.put(`/api/v1/accounts/${login}/unarchive`);
|
|
544
728
|
}
|
|
729
|
+
/**
|
|
730
|
+
* Update account information (partial update)
|
|
731
|
+
* All fields are optional, only send the ones you want to update
|
|
732
|
+
*/
|
|
733
|
+
async update(login, request) {
|
|
734
|
+
return this.http.put(`/api/v1/accounts/${login}`, request);
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* Adjust balance or credit for an account
|
|
738
|
+
* The adjustment is relative: amount is added or subtracted from current value
|
|
739
|
+
*/
|
|
740
|
+
async balance(login, request) {
|
|
741
|
+
return this.http.put(`/api/v1/accounts/${login}/adjust`, request);
|
|
742
|
+
}
|
|
545
743
|
};
|
|
546
744
|
|
|
547
745
|
// src/api/trading-groups.ts
|
|
@@ -838,9 +1036,9 @@ var PipsendClient = class {
|
|
|
838
1036
|
return this.wsManager?.isWebSocketConnected() ?? false;
|
|
839
1037
|
},
|
|
840
1038
|
/**
|
|
841
|
-
* Subscribes to
|
|
1039
|
+
* Subscribes to WebSocket channels
|
|
842
1040
|
* @example
|
|
843
|
-
* client.stream.subscribe(['
|
|
1041
|
+
* client.stream.subscribe(['positions:new', 'positions:closed']);
|
|
844
1042
|
*/
|
|
845
1043
|
subscribe: (channels) => {
|
|
846
1044
|
if (!this.wsManager) {
|
|
@@ -849,7 +1047,7 @@ var PipsendClient = class {
|
|
|
849
1047
|
this.wsManager.subscribe(channels);
|
|
850
1048
|
},
|
|
851
1049
|
/**
|
|
852
|
-
* Unsubscribes from
|
|
1050
|
+
* Unsubscribes from WebSocket channels
|
|
853
1051
|
*/
|
|
854
1052
|
unsubscribe: (channels) => {
|
|
855
1053
|
if (!this.wsManager) {
|
|
@@ -864,40 +1062,81 @@ var PipsendClient = class {
|
|
|
864
1062
|
return this.wsManager?.getSubscribedChannels() ?? [];
|
|
865
1063
|
},
|
|
866
1064
|
/**
|
|
867
|
-
* Listens to
|
|
1065
|
+
* Listens to position opened events
|
|
1066
|
+
*/
|
|
1067
|
+
onPositionOpened: (callback) => {
|
|
1068
|
+
if (!this.wsManager) {
|
|
1069
|
+
throw new WebSocketError("WebSocket not enabled");
|
|
1070
|
+
}
|
|
1071
|
+
this.wsManager.on("position:opened", callback);
|
|
1072
|
+
},
|
|
1073
|
+
/**
|
|
1074
|
+
* Listens to position closed events (includes partial closes)
|
|
1075
|
+
*/
|
|
1076
|
+
onPositionClosed: (callback) => {
|
|
1077
|
+
if (!this.wsManager) {
|
|
1078
|
+
throw new WebSocketError("WebSocket not enabled");
|
|
1079
|
+
}
|
|
1080
|
+
this.wsManager.on("position:closed", callback);
|
|
1081
|
+
},
|
|
1082
|
+
/**
|
|
1083
|
+
* Listens to position updated events (throttled to max 1 per 2 seconds)
|
|
1084
|
+
*/
|
|
1085
|
+
onPositionUpdated: (callback) => {
|
|
1086
|
+
if (!this.wsManager) {
|
|
1087
|
+
throw new WebSocketError("WebSocket not enabled");
|
|
1088
|
+
}
|
|
1089
|
+
this.wsManager.on("position:updated", callback);
|
|
1090
|
+
},
|
|
1091
|
+
/**
|
|
1092
|
+
* Listens to balance updated events
|
|
1093
|
+
*/
|
|
1094
|
+
onBalanceUpdated: (callback) => {
|
|
1095
|
+
if (!this.wsManager) {
|
|
1096
|
+
throw new WebSocketError("WebSocket not enabled");
|
|
1097
|
+
}
|
|
1098
|
+
this.wsManager.on("balance:updated", callback);
|
|
1099
|
+
},
|
|
1100
|
+
// Legacy methods (deprecated but kept for compatibility)
|
|
1101
|
+
/**
|
|
1102
|
+
* @deprecated Use onPositionUpdated instead
|
|
868
1103
|
*/
|
|
869
1104
|
onPriceUpdate: (callback) => {
|
|
1105
|
+
console.warn("\u26A0\uFE0F onPriceUpdate is deprecated. Use onPositionUpdated instead.");
|
|
870
1106
|
if (!this.wsManager) {
|
|
871
1107
|
throw new WebSocketError("WebSocket not enabled");
|
|
872
1108
|
}
|
|
873
|
-
this.wsManager.on("
|
|
1109
|
+
this.wsManager.on("position:updated", callback);
|
|
874
1110
|
},
|
|
875
1111
|
/**
|
|
876
|
-
*
|
|
1112
|
+
* @deprecated Use onPositionOpened/onPositionClosed instead
|
|
877
1113
|
*/
|
|
878
1114
|
onOrderUpdate: (callback) => {
|
|
1115
|
+
console.warn("\u26A0\uFE0F onOrderUpdate is deprecated. Use onPositionOpened/onPositionClosed instead.");
|
|
879
1116
|
if (!this.wsManager) {
|
|
880
1117
|
throw new WebSocketError("WebSocket not enabled");
|
|
881
1118
|
}
|
|
882
|
-
this.wsManager.on("
|
|
1119
|
+
this.wsManager.on("position:opened", callback);
|
|
883
1120
|
},
|
|
884
1121
|
/**
|
|
885
|
-
*
|
|
1122
|
+
* @deprecated Use onPositionUpdated instead
|
|
886
1123
|
*/
|
|
887
1124
|
onPositionUpdate: (callback) => {
|
|
1125
|
+
console.warn("\u26A0\uFE0F onPositionUpdate is deprecated. Use onPositionUpdated instead.");
|
|
888
1126
|
if (!this.wsManager) {
|
|
889
1127
|
throw new WebSocketError("WebSocket not enabled");
|
|
890
1128
|
}
|
|
891
|
-
this.wsManager.on("position", callback);
|
|
1129
|
+
this.wsManager.on("position:updated", callback);
|
|
892
1130
|
},
|
|
893
1131
|
/**
|
|
894
|
-
*
|
|
1132
|
+
* @deprecated Use onBalanceUpdated instead
|
|
895
1133
|
*/
|
|
896
1134
|
onBalanceUpdate: (callback) => {
|
|
1135
|
+
console.warn("\u26A0\uFE0F onBalanceUpdate is deprecated. Use onBalanceUpdated instead.");
|
|
897
1136
|
if (!this.wsManager) {
|
|
898
1137
|
throw new WebSocketError("WebSocket not enabled");
|
|
899
1138
|
}
|
|
900
|
-
this.wsManager.on("balance", callback);
|
|
1139
|
+
this.wsManager.on("balance:updated", callback);
|
|
901
1140
|
},
|
|
902
1141
|
/**
|
|
903
1142
|
* Listens to connection events
|
|
@@ -941,7 +1180,7 @@ var PipsendClient = class {
|
|
|
941
1180
|
timezone: config.timezone ?? "UTC"
|
|
942
1181
|
};
|
|
943
1182
|
this.authManager = new AuthManager(this.config);
|
|
944
|
-
this.http = new HttpClient(this.config.server);
|
|
1183
|
+
this.http = new HttpClient(this.config.server, this.authManager);
|
|
945
1184
|
this.accounts = new AccountsAPI(this.http);
|
|
946
1185
|
this.tradingGroups = new TradingGroupsAPI(this.http);
|
|
947
1186
|
this.marketData = new MarketDataAPI(this.http);
|