@pipsend/sdk 0.3.0 โ†’ 0.3.1

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 CHANGED
@@ -36,12 +36,12 @@ pnpm add @pipsend/sdk
36
36
  The SDK uses JWT-based authentication with automatic token refresh.
37
37
 
38
38
  ```typescript
39
- import { createClient } from '@pipsend/sdk';
39
+ import { createClient } from "@pipsend/sdk";
40
40
 
41
41
  const client = createClient({
42
- server: 'http://localhost:8080',
43
- login: '1000', // Your admin/API login
44
- password: 'YourPassword' // Your admin/API password
42
+ server: "http://localhost:8080",
43
+ login: "1000", // Your admin/API login
44
+ password: "YourPassword", // Your admin/API password
45
45
  });
46
46
 
47
47
  // The SDK automatically:
@@ -69,7 +69,7 @@ await client.logout();
69
69
 
70
70
  // Get current token info
71
71
  const tokenInfo = client.getTokenInfo();
72
- console.log('Token expires at:', tokenInfo?.expiresAt);
72
+ console.log("Token expires at:", tokenInfo?.expiresAt);
73
73
  ```
74
74
 
75
75
  ---
@@ -77,45 +77,45 @@ console.log('Token expires at:', tokenInfo?.expiresAt);
77
77
  ## ๐Ÿ”ง Quick Start
78
78
 
79
79
  ```typescript
80
- import { createClient } from '@pipsend/sdk';
80
+ import { createClient } from "@pipsend/sdk";
81
81
 
82
82
  // Create authenticated client
83
83
  const client = createClient({
84
- server: 'http://localhost:8080',
85
- login: '1000',
86
- password: 'DemoMaster'
84
+ server: "http://localhost:8080",
85
+ login: "1000",
86
+ password: "DemoMaster",
87
87
  });
88
88
 
89
89
  const login = 50001;
90
90
 
91
91
  // List accounts with filters
92
92
  const accounts = await client.accounts.list({
93
- state: 'active',
94
- country: 'Mexico',
95
- min_balance: 1000
93
+ state: "active",
94
+ country: "Mexico",
95
+ min_balance: 1000,
96
96
  });
97
97
 
98
98
  // Open a trade
99
99
  const trade = await client.trades.open({
100
100
  login,
101
- symbol: 'EURUSD',
102
- action: 'buy',
103
- type: 'market',
101
+ symbol: "EURUSD",
102
+ action: "buy",
103
+ type: "market",
104
104
  volume: 1.0,
105
- stop_loss: 1.0850,
106
- take_profit: 1.0950
105
+ stop_loss: 1.085,
106
+ take_profit: 1.095,
107
107
  });
108
108
 
109
109
  // Get market data
110
110
  const candles = await client.marketData.getCandles({
111
- symbol: 'BTCUSD',
112
- timeframe: '1h',
113
- limit: 100
111
+ symbol: "BTCUSD",
112
+ timeframe: "1h",
113
+ limit: 100,
114
114
  });
115
115
 
116
116
  // WebSocket real-time updates
117
117
  client.stream.onPriceUpdate((price) => {
118
- console.log('Price update:', price);
118
+ console.log("Price update:", price);
119
119
  });
120
120
 
121
121
  await client.stream.connect();
@@ -130,32 +130,32 @@ Manage accounts with advanced filtering and statistics.
130
130
  ```typescript
131
131
  // Create a new trading account
132
132
  const newAccount = await client.accounts.create({
133
- trading_group: 'Premium',
134
- country: 'MX',
135
- master_password: 'SecurePass123!',
136
- investor_password: 'InvestorPass123!',
137
- email: 'trader@example.com',
138
- first_name: 'John',
139
- last_name: 'Doe',
133
+ trading_group: "Premium",
134
+ country: "MX",
135
+ master_password: "SecurePass123!",
136
+ investor_password: "InvestorPass123!",
137
+ email: "trader@example.com",
138
+ first_name: "John",
139
+ last_name: "Doe",
140
140
  leverage: 100,
141
- state: 'active'
141
+ state: "active",
142
142
  });
143
143
 
144
144
  // List accounts with filters
145
145
  const accounts = await client.accounts.list({
146
- state: 'active',
147
- country: 'Mexico,United States',
148
- trading_group: 'Premium',
146
+ state: "active",
147
+ country: "Mexico,United States",
148
+ trading_group: "Premium",
149
149
  min_balance: 1000,
150
150
  max_balance: 50000,
151
151
  page: 1,
152
- per_page: 20
152
+ per_page: 20,
153
153
  });
154
154
 
155
155
  // Get statistics with filters
156
156
  const stats = await client.accounts.getStatistics({
157
- country: 'Mexico',
158
- state: 'active'
157
+ country: "Mexico",
158
+ state: "active",
159
159
  });
160
160
 
161
161
  // Get all account logins
@@ -163,18 +163,15 @@ const logins = await client.accounts.getLogins();
163
163
 
164
164
  // Get account status/metrics (balance, equity, credit, margin)
165
165
  const status = await client.accounts.getStatus(50001);
166
- console.log('Balance:', status.data.balance);
167
- console.log('Equity:', status.data.equity);
168
- console.log('Credit:', status.data.credit);
169
- console.log('Margin:', status.data.margin);
166
+ console.log("Balance:", status.data.balance);
167
+ console.log("Equity:", status.data.equity);
168
+ console.log("Credit:", status.data.credit);
169
+ console.log("Margin:", status.data.margin);
170
170
 
171
- // Change passwords
172
- await client.accounts.changeMasterPassword(50001, {
173
- new_password: 'NewPass123!'
174
- });
175
-
176
- await client.accounts.changeInvestorPassword(50001, {
177
- new_password: 'InvestorPass123!'
171
+ // Change passwords (master and/or investor)
172
+ await client.accounts.changePassword(50001, {
173
+ master: "NewMasterPass123!",
174
+ investor: "NewInvestorPass123!",
178
175
  });
179
176
 
180
177
  // Archive/Unarchive
@@ -183,30 +180,30 @@ await client.accounts.unarchive(50001);
183
180
 
184
181
  // Update account information (partial update)
185
182
  await client.accounts.update(50001, {
186
- email: 'newemail@example.com',
183
+ email: "newemail@example.com",
187
184
  leverage: 200,
188
- city: 'Los Angeles',
189
- trading_group: 'Premium'
185
+ city: "Los Angeles",
186
+ trading_group: "Premium",
190
187
  });
191
188
 
192
189
  // Adjust balance or credit
193
190
  await client.accounts.balance(50001, {
194
- type: 'balance',
195
- amount: 500.00,
196
- comment: 'Client deposit'
191
+ type: "balance",
192
+ amount: 500.0,
193
+ comment: "Client deposit",
197
194
  });
198
195
 
199
196
  await client.accounts.balance(50001, {
200
- type: 'credit',
201
- amount: 1000.00,
202
- comment: 'Credit line increase'
197
+ type: "credit",
198
+ amount: 1000.0,
199
+ comment: "Credit line increase",
203
200
  });
204
201
 
205
202
  // Subtract balance
206
203
  await client.accounts.balance(50001, {
207
- type: 'balance',
208
- amount: -200.00,
209
- comment: 'Withdrawal request'
204
+ type: "balance",
205
+ amount: -200.0,
206
+ comment: "Withdrawal request",
210
207
  });
211
208
  ```
212
209
 
@@ -217,35 +214,35 @@ Manage pending orders with statistics and validation.
217
214
  ```typescript
218
215
  // List orders with advanced filters
219
216
  const orders = await client.orders.list({
220
- login: '50001',
221
- symbol: 'EURUSD,GBPUSD',
222
- order_type: 'limit',
223
- status: 'new,partial',
224
- created_from: '2025-01-01T00:00:00Z',
225
- created_to: '2025-01-31T23:59:59Z',
217
+ login: "50001",
218
+ symbol: "EURUSD,GBPUSD",
219
+ order_type: "limit",
220
+ status: "new,partial",
221
+ created_from: "2025-01-01T00:00:00Z",
222
+ created_to: "2025-01-31T23:59:59Z",
226
223
  price_min: 1.08,
227
- price_max: 1.10,
228
- sort_by: 'created_at',
229
- sort_order: 'desc'
224
+ price_max: 1.1,
225
+ sort_by: "created_at",
226
+ sort_order: "desc",
230
227
  });
231
228
 
232
229
  // Get statistics grouped by symbol
233
230
  const stats = await client.orders.getStats({
234
- login: '50001',
235
- group_by: 'symbol'
231
+ login: "50001",
232
+ group_by: "symbol",
236
233
  });
237
234
 
238
235
  // Get totals by order type
239
236
  const totals = await client.orders.getTotals({
240
- login: '50001',
241
- group_by: 'order_type'
237
+ login: "50001",
238
+ group_by: "order_type",
242
239
  });
243
240
 
244
241
  // Update order
245
242
  await client.orders.update(12345, {
246
243
  login: 50001,
247
- stop_loss: 1.0800,
248
- take_profit: 1.0950
244
+ stop_loss: 1.08,
245
+ take_profit: 1.095,
249
246
  });
250
247
 
251
248
  // Delete order
@@ -255,8 +252,8 @@ await client.orders.delete(12345, { login: 50001 });
255
252
  const checkResult = await client.orders.check({
256
253
  filters: {
257
254
  logins: [50001],
258
- statuses: ['new']
259
- }
255
+ statuses: ["new"],
256
+ },
260
257
  });
261
258
  ```
262
259
 
@@ -267,31 +264,31 @@ Manage open positions with recalculation support.
267
264
  ```typescript
268
265
  // List positions with filters
269
266
  const positions = await client.positions.list({
270
- login: '50001',
271
- symbol: 'EURUSD',
272
- state: 'open',
267
+ login: "50001",
268
+ symbol: "EURUSD",
269
+ state: "open",
273
270
  profit_min: 100,
274
- profit_max: 1000
271
+ profit_max: 1000,
275
272
  });
276
273
 
277
274
  // Get statistics grouped by type
278
275
  const stats = await client.positions.getStats({
279
- login: '50001',
280
- state: 'open',
281
- group_by: 'type'
276
+ login: "50001",
277
+ state: "open",
278
+ group_by: "type",
282
279
  });
283
280
 
284
281
  // Get totals by symbol
285
282
  const totals = await client.positions.getTotals({
286
- login: '50001',
287
- group_by: 'symbol'
283
+ login: "50001",
284
+ group_by: "symbol",
288
285
  });
289
286
 
290
287
  // Update position
291
288
  await client.positions.update(1, {
292
289
  login: 50001,
293
290
  stop_loss: 1.0875,
294
- take_profit: 1.0975
291
+ take_profit: 1.0975,
295
292
  });
296
293
 
297
294
  // Delete position
@@ -301,8 +298,8 @@ await client.positions.delete(1, { login: 50001 });
301
298
  const checkResult = await client.positions.check({
302
299
  filters: {
303
300
  logins: [50001],
304
- states: ['open']
305
- }
301
+ states: ["open"],
302
+ },
306
303
  });
307
304
  ```
308
305
 
@@ -314,22 +311,22 @@ Execute trading operations with margin checking.
314
311
  // Check margin before trading
315
312
  const marginCheck = await client.trades.checkMargin({
316
313
  login: 50001,
317
- symbol: 'EURUSD',
318
- action: 'buy',
319
- volume: 1.0
314
+ symbol: "EURUSD",
315
+ action: "buy",
316
+ volume: 1.0,
320
317
  });
321
318
 
322
319
  if (marginCheck.can_execute) {
323
320
  // Open trade
324
321
  const trade = await client.trades.open({
325
322
  login: 50001,
326
- symbol: 'EURUSD',
327
- action: 'buy',
328
- type: 'market',
323
+ symbol: "EURUSD",
324
+ action: "buy",
325
+ type: "market",
329
326
  volume: 1.0,
330
- stop_loss: 1.0850,
331
- take_profit: 1.0950,
332
- comment: 'API Trade'
327
+ stop_loss: 1.085,
328
+ take_profit: 1.095,
329
+ comment: "API Trade",
333
330
  });
334
331
 
335
332
  // Modify trade
@@ -337,17 +334,17 @@ if (marginCheck.can_execute) {
337
334
  login: 50001,
338
335
  position_id: trade.position_id,
339
336
  stop_loss: 1.0875,
340
- take_profit: 1.0975
337
+ take_profit: 1.0975,
341
338
  });
342
339
 
343
340
  // Calculate potential profit
344
341
  const profitCalc = await client.trades.calculateProfit({
345
342
  login: 50001,
346
- symbol: 'EURUSD',
347
- action: 'buy',
343
+ symbol: "EURUSD",
344
+ action: "buy",
348
345
  volume: 1.0,
349
- open_price: 1.0900,
350
- close_price: 1.0950
346
+ open_price: 1.09,
347
+ close_price: 1.095,
351
348
  });
352
349
 
353
350
  // Close trade (partial or full)
@@ -355,20 +352,20 @@ if (marginCheck.can_execute) {
355
352
  login: 50001,
356
353
  position_id: trade.position_id,
357
354
  volume: 0.5, // Partial close
358
- comment: 'Taking profit'
355
+ comment: "Taking profit",
359
356
  });
360
357
  }
361
358
 
362
359
  // Force price (for historical data import)
363
360
  const historicalTrade = await client.trades.open({
364
361
  login: 50001,
365
- symbol: 'EURUSD',
366
- action: 'buy',
367
- type: 'market',
362
+ symbol: "EURUSD",
363
+ action: "buy",
364
+ type: "market",
368
365
  volume: 1.0,
369
- price: 1.0850,
366
+ price: 1.085,
370
367
  force_price: true,
371
- force_timestamp: '2025-01-15T10:30:00Z'
368
+ force_timestamp: "2025-01-15T10:30:00Z",
372
369
  });
373
370
  ```
374
371
 
@@ -379,37 +376,37 @@ Query historical market data (minimum 1 hour old).
379
376
  ```typescript
380
377
  // Get candles with filters
381
378
  const candles = await client.marketData.getCandles({
382
- symbol: 'BTCUSD,ETHUSD',
383
- timeframe: '1h',
384
- from: '2025-01-01T00:00:00Z',
385
- to: '2025-01-02T00:00:00Z',
379
+ symbol: "BTCUSD,ETHUSD",
380
+ timeframe: "1h",
381
+ from: "2025-01-01T00:00:00Z",
382
+ to: "2025-01-02T00:00:00Z",
386
383
  min_volume: 1000,
387
384
  max_volume: 50000,
388
- sort: 'volume',
389
- order: 'desc',
390
- limit: 100
385
+ sort: "volume",
386
+ order: "desc",
387
+ limit: 100,
391
388
  });
392
389
 
393
390
  // Get last 100 candles
394
391
  const recentCandles = await client.marketData.getCandles({
395
- symbol: 'BTCUSD',
396
- timeframe: '1m',
392
+ symbol: "BTCUSD",
393
+ timeframe: "1m",
397
394
  limit: 100,
398
- order: 'desc'
395
+ order: "desc",
399
396
  });
400
397
 
401
398
  // Get symbols with filters
402
399
  const symbols = await client.marketData.getSymbols({
403
- group: 'CRYPTO_MAJOR',
400
+ group: "CRYPTO_MAJOR",
404
401
  has_data: true,
405
- search: 'bitcoin'
402
+ search: "bitcoin",
406
403
  });
407
404
 
408
405
  // Get groups hierarchy
409
406
  const groups = await client.marketData.getGroups({
410
407
  root_only: true,
411
- sort: 'symbol_count',
412
- order: 'desc'
408
+ sort: "symbol_count",
409
+ order: "desc",
413
410
  });
414
411
  ```
415
412
 
@@ -425,7 +422,7 @@ Manage trading groups and their statistics.
425
422
  // List trading groups
426
423
  const groups = await client.tradingGroups.list({
427
424
  page: 1,
428
- per_page: 20
425
+ per_page: 20,
429
426
  });
430
427
 
431
428
  // Get statistics
@@ -439,13 +436,13 @@ Real-time updates for positions and balance with manual channel subscription.
439
436
  ```typescript
440
437
  // Enable WebSocket in config
441
438
  const client = createClient({
442
- server: 'http://localhost:8080',
443
- login: '1000',
444
- password: 'DemoMaster',
439
+ server: "http://localhost:8080",
440
+ login: "1000",
441
+ password: "DemoMaster",
445
442
  websocket: {
446
443
  enabled: true,
447
- autoConnect: false
448
- }
444
+ autoConnect: false,
445
+ },
449
446
  });
450
447
 
451
448
  // Connect to WebSocket
@@ -453,49 +450,56 @@ await client.stream.connect();
453
450
 
454
451
  // Subscribe to channels
455
452
  client.stream.subscribe([
456
- 'positions:new', // New positions opened
457
- 'positions:closed', // Positions closed (total and partial)
458
- 'positions:updated', // Position PnL updates (throttled to 1 per 2s)
459
- 'accounts:balance' // Balance updates
453
+ "positions:new", // New positions opened
454
+ "positions:closed", // Positions closed (total and partial)
455
+ "positions:updated", // Position PnL updates (throttled to 1 per 2s)
456
+ "accounts:balance", // Balance updates
460
457
  ]);
461
458
 
462
459
  // Listen to position opened events
463
460
  client.stream.onPositionOpened((event) => {
464
461
  const pos = event.position;
465
- console.log('Position opened:', pos.symbol, pos.side === 1 ? 'LONG' : 'SHORT', pos.qty);
462
+ console.log(
463
+ "Position opened:",
464
+ pos.symbol,
465
+ pos.side === 1 ? "LONG" : "SHORT",
466
+ pos.qty,
467
+ );
466
468
  });
467
469
 
468
470
  // Listen to position closed events
469
471
  client.stream.onPositionClosed((event) => {
470
472
  const pos = event.position;
471
- console.log('Position closed:', pos.symbol, 'PnL:', pos.net_pnl);
473
+ console.log("Position closed:", pos.symbol, "PnL:", pos.net_pnl);
472
474
  });
473
475
 
474
476
  // Listen to position updated events (throttled)
475
477
  client.stream.onPositionUpdated((event) => {
476
478
  const pos = event.position;
477
- console.log('Position update:', pos.position_id, 'PnL:', pos.unrealized_pnl);
479
+ console.log("Position update:", pos.position_id, "PnL:", pos.unrealized_pnl);
478
480
  });
479
481
 
480
482
  // Listen to balance updates
481
483
  client.stream.onBalanceUpdated((event) => {
482
- console.log('Balance:', event.balance, 'Equity:', event.equity);
484
+ console.log("Balance:", event.balance, "Equity:", event.equity);
483
485
  });
484
486
 
485
487
  // Unsubscribe from channels
486
- client.stream.unsubscribe(['positions:updated']);
488
+ client.stream.unsubscribe(["positions:updated"]);
487
489
 
488
490
  // Disconnect
489
491
  client.stream.disconnect();
490
492
  ```
491
493
 
492
494
  **Available Channels**:
495
+
493
496
  - `positions:new` - New position opened
494
497
  - `positions:closed` - Position closed (total or partial)
495
498
  - `positions:updated` - PnL updates (throttled to max 1 per 2 seconds)
496
499
  - `accounts:balance` - Balance changes
497
500
 
498
501
  **Features**:
502
+
499
503
  - Manual subscription to specific channels
500
504
  - Auto-reconnect with exponential backoff
501
505
  - Heartbeat/ping-pong mechanism
@@ -510,9 +514,9 @@ See [WebSocket API Documentation](docs/WEBSOCKET_API.md) for complete guide.
510
514
 
511
515
  ```typescript
512
516
  const client = createClient({
513
- server: 'http://localhost:8080', // Required: API server URL
514
- login: '1000', // Required: Admin/API login
515
- password: 'YourPassword' // Required: Admin/API password
517
+ server: "http://localhost:8080", // Required: API server URL
518
+ login: "1000", // Required: Admin/API login
519
+ password: "YourPassword", // Required: Admin/API password
516
520
  });
517
521
  ```
518
522
 
@@ -520,39 +524,40 @@ const client = createClient({
520
524
 
521
525
  ```typescript
522
526
  const client = createClient({
523
- server: 'http://localhost:8080',
524
- login: '1000',
525
- password: 'YourPassword',
526
-
527
+ server: "http://localhost:8080",
528
+ login: "1000",
529
+ password: "YourPassword",
530
+
527
531
  // WebSocket configuration (optional)
528
532
  websocket: {
529
- enabled: true, // Enable WebSocket support
530
- autoConnect: false, // Auto-connect on client creation
531
- autoReconnect: true, // Auto-reconnect on disconnect
532
- maxReconnectAttempts: 5, // Max reconnection attempts
533
- heartbeatInterval: 30000 // Heartbeat interval in ms
534
- }
533
+ enabled: true, // Enable WebSocket support
534
+ autoConnect: false, // Auto-connect on client creation
535
+ autoReconnect: true, // Auto-reconnect on disconnect
536
+ maxReconnectAttempts: 5, // Max reconnection attempts
537
+ heartbeatInterval: 30000, // Heartbeat interval in ms
538
+ },
535
539
  });
536
540
  ```
537
541
 
538
542
  ### Configuration Options
539
543
 
540
- | Option | Type | Required | Default | Description |
541
- |--------|------|----------|---------|-------------|
542
- | `server` | string | โœ… Yes | - | Pipsend API server URL |
543
- | `login` | string | โœ… Yes | - | Admin/API login for authentication |
544
- | `password` | string | โœ… Yes | - | Admin/API password |
545
- | `websocket.enabled` | boolean | No | `false` | Enable WebSocket support |
546
- | `websocket.autoConnect` | boolean | No | `false` | Auto-connect on creation |
547
- | `websocket.autoReconnect` | boolean | No | `true` | Auto-reconnect on disconnect |
548
- | `websocket.maxReconnectAttempts` | number | No | `5` | Max reconnection attempts |
549
- | `websocket.heartbeatInterval` | number | No | `30000` | Heartbeat interval (ms) |
544
+ | Option | Type | Required | Default | Description |
545
+ | -------------------------------- | ------- | -------- | ------- | ---------------------------------- |
546
+ | `server` | string | โœ… Yes | - | Pipsend API server URL |
547
+ | `login` | string | โœ… Yes | - | Admin/API login for authentication |
548
+ | `password` | string | โœ… Yes | - | Admin/API password |
549
+ | `websocket.enabled` | boolean | No | `false` | Enable WebSocket support |
550
+ | `websocket.autoConnect` | boolean | No | `false` | Auto-connect on creation |
551
+ | `websocket.autoReconnect` | boolean | No | `true` | Auto-reconnect on disconnect |
552
+ | `websocket.maxReconnectAttempts` | number | No | `5` | Max reconnection attempts |
553
+ | `websocket.heartbeatInterval` | number | No | `30000` | Heartbeat interval (ms) |
550
554
 
551
555
  ## ๐Ÿ“ฆ API Response Structure
552
556
 
553
557
  All API endpoints return a consistent response structure:
554
558
 
555
559
  ### Success Response (without pagination)
560
+
556
561
  ```typescript
557
562
  {
558
563
  status: "success",
@@ -562,6 +567,7 @@ All API endpoints return a consistent response structure:
562
567
  ```
563
568
 
564
569
  ### Success Response (with pagination)
570
+
565
571
  ```typescript
566
572
  {
567
573
  status: "success",
@@ -579,6 +585,7 @@ All API endpoints return a consistent response structure:
579
585
  ```
580
586
 
581
587
  ### Error Response
588
+
582
589
  ```typescript
583
590
  {
584
591
  status: "error",
@@ -596,10 +603,12 @@ All API endpoints return a consistent response structure:
596
603
  ### Common Status Codes
597
604
 
598
605
  **Success:**
606
+
599
607
  - `SUCCESS` - Operation successful
600
608
  - `CREATED` - Resource created successfully
601
609
 
602
610
  **Errors:**
611
+
603
612
  - `VALIDATION_ERROR` (400) - Invalid parameters
604
613
  - `BAD_REQUEST` (400) - Invalid request
605
614
  - `UNAUTHORIZED` (401) - Authentication required
@@ -609,6 +618,7 @@ All API endpoints return a consistent response structure:
609
618
  - `INTERNAL_ERROR` (500) - Server error
610
619
 
611
620
  **Market Data Specific:**
621
+
612
622
  - `SYMBOL_NOT_FOUND` (404) - Symbol not found
613
623
  - `INVALID_TIMEFRAME` (400) - Invalid timeframe
614
624
  - `TIME_RANGE_TOO_LARGE` (400) - Time range exceeds maximum
@@ -619,21 +629,23 @@ All API endpoints return a consistent response structure:
619
629
  ### Pagination
620
630
 
621
631
  **Option 1: Get all results (no pagination)**
632
+
622
633
  ```typescript
623
634
  // Returns all results in a single array
624
635
  const accounts = await client.accounts.list({
625
- state: 'active'
636
+ state: "active",
626
637
  });
627
638
  // Response: { status, status_code, data: [...] }
628
639
  ```
629
640
 
630
641
  **Option 2: Paginated results**
642
+
631
643
  ```typescript
632
644
  // Returns paginated results with metadata
633
645
  const accounts = await client.accounts.list({
634
- state: 'active',
646
+ state: "active",
635
647
  page: 1,
636
- per_page: 20
648
+ per_page: 20,
637
649
  });
638
650
  // Response: { status, status_code, data: [...], meta: {...} }
639
651
 
@@ -643,26 +655,27 @@ let hasMore = true;
643
655
 
644
656
  while (hasMore) {
645
657
  const response = await client.accounts.list({
646
- state: 'active',
658
+ state: "active",
647
659
  page,
648
- per_page: 50
660
+ per_page: 50,
649
661
  });
650
-
662
+
651
663
  // Process response.data
652
664
  console.log(`Page ${page}:`, response.data.length);
653
-
665
+
654
666
  hasMore = response.meta.has_next;
655
667
  page++;
656
668
  }
657
669
  ```
658
670
 
659
671
  **Option 3: Limit results (ignores pagination)**
672
+
660
673
  ```typescript
661
674
  // Get specific number of results
662
675
  const candles = await client.marketData.getCandles({
663
- symbol: 'BTCUSD',
664
- timeframe: '1h',
665
- limit: 100 // Max: 10,000 for candles
676
+ symbol: "BTCUSD",
677
+ timeframe: "1h",
678
+ limit: 100, // Max: 10,000 for candles
666
679
  });
667
680
  ```
668
681
 
@@ -673,17 +686,17 @@ Many filters accept comma-separated values:
673
686
  ```typescript
674
687
  // Multiple symbols (OR logic)
675
688
  const positions = await client.positions.list({
676
- symbol: 'EURUSD,GBPUSD,USDJPY' // Positions in ANY of these symbols
689
+ symbol: "EURUSD,GBPUSD,USDJPY", // Positions in ANY of these symbols
677
690
  });
678
691
 
679
692
  // Multiple countries
680
693
  const accounts = await client.accounts.list({
681
- country: 'Mexico,United States,Canada'
694
+ country: "Mexico,United States,Canada",
682
695
  });
683
696
 
684
697
  // Multiple states
685
698
  const orders = await client.orders.list({
686
- status: 'new,partial' // Orders with status new OR partial
699
+ status: "new,partial", // Orders with status new OR partial
687
700
  });
688
701
  ```
689
702
 
@@ -694,16 +707,16 @@ All date parameters must be in **ISO 8601 / RFC3339 format** (UTC):
694
707
  ```typescript
695
708
  // Correct format
696
709
  const positions = await client.positions.list({
697
- opened_from: '2025-01-01T00:00:00Z',
698
- opened_to: '2025-01-31T23:59:59Z'
710
+ opened_from: "2025-01-01T00:00:00Z",
711
+ opened_to: "2025-01-31T23:59:59Z",
699
712
  });
700
713
 
701
714
  // Also valid
702
715
  const candles = await client.marketData.getCandles({
703
- symbol: 'BTCUSD',
704
- timeframe: '1h',
705
- from: '2025-01-15T10:30:00Z',
706
- to: '2025-01-15T18:30:00Z'
716
+ symbol: "BTCUSD",
717
+ timeframe: "1h",
718
+ from: "2025-01-15T10:30:00Z",
719
+ to: "2025-01-15T18:30:00Z",
707
720
  });
708
721
  ```
709
722
 
@@ -717,21 +730,21 @@ Use `min_*` and `max_*` for numeric ranges:
717
730
  // Balance range
718
731
  const accounts = await client.accounts.list({
719
732
  min_balance: 1000,
720
- max_balance: 50000
733
+ max_balance: 50000,
721
734
  });
722
735
 
723
736
  // Profit range
724
737
  const positions = await client.positions.list({
725
738
  profit_min: 100,
726
- profit_max: 1000
739
+ profit_max: 1000,
727
740
  });
728
741
 
729
742
  // Volume range
730
743
  const candles = await client.marketData.getCandles({
731
- symbol: 'BTCUSD',
732
- timeframe: '1h',
744
+ symbol: "BTCUSD",
745
+ timeframe: "1h",
733
746
  min_volume: 1000,
734
- max_volume: 50000
747
+ max_volume: 50000,
735
748
  });
736
749
  ```
737
750
 
@@ -741,16 +754,16 @@ Most list endpoints support sorting:
741
754
 
742
755
  ```typescript
743
756
  const orders = await client.orders.list({
744
- login: '50001',
745
- sort_by: 'created_at', // Field to sort by
746
- sort_order: 'desc' // 'asc' or 'desc'
757
+ login: "50001",
758
+ sort_by: "created_at", // Field to sort by
759
+ sort_order: "desc", // 'asc' or 'desc'
747
760
  });
748
761
 
749
762
  const candles = await client.marketData.getCandles({
750
- symbol: 'BTCUSD',
751
- timeframe: '1h',
752
- sort: 'volume', // Some endpoints use 'sort'
753
- order: 'desc' // instead of 'sort_by'/'sort_order'
763
+ symbol: "BTCUSD",
764
+ timeframe: "1h",
765
+ sort: "volume", // Some endpoints use 'sort'
766
+ order: "desc", // instead of 'sort_by'/'sort_order'
754
767
  });
755
768
  ```
756
769
 
@@ -761,28 +774,27 @@ All errors thrown by the SDK are instances of `PipsendError` with detailed infor
761
774
  ### Basic Error Handling
762
775
 
763
776
  ```typescript
764
- import { PipsendError } from '@pipsend/sdk';
777
+ import { PipsendError } from "@pipsend/sdk";
765
778
 
766
779
  try {
767
780
  const trade = await client.trades.open({
768
781
  login: 50001,
769
- symbol: 'EURUSD',
770
- action: 'buy',
771
- type: 'market',
772
- volume: 1.0
782
+ symbol: "EURUSD",
783
+ action: "buy",
784
+ type: "market",
785
+ volume: 1.0,
773
786
  });
774
-
775
- console.log('Trade opened:', trade.position_id);
776
-
787
+
788
+ console.log("Trade opened:", trade.position_id);
777
789
  } catch (error) {
778
790
  if (error instanceof PipsendError) {
779
- console.error('Error code:', error.code);
780
- console.error('Status code:', error.statusCode);
781
- console.error('Message:', error.message);
782
-
791
+ console.error("Error code:", error.code);
792
+ console.error("Status code:", error.statusCode);
793
+ console.error("Message:", error.message);
794
+
783
795
  // Check if it's a validation error
784
796
  if (error.isValidationError()) {
785
- console.error('Validation errors:', error.errors);
797
+ console.error("Validation errors:", error.errors);
786
798
  // Get formatted message with all details
787
799
  console.error(error.getDetailedMessage());
788
800
  }
@@ -797,26 +809,26 @@ When the API returns validation errors, the SDK provides detailed field-level in
797
809
  ```typescript
798
810
  try {
799
811
  const account = await client.accounts.create({
800
- trading_group: 'InvalidGroup',
801
- country: 'XYZ',
802
- master_password: 'short',
803
- investor_password: 'short',
804
- email: 'invalid-email',
805
- first_name: 'John',
806
- last_name: 'Doe'
812
+ trading_group: "InvalidGroup",
813
+ country: "XYZ",
814
+ master_password: "short",
815
+ investor_password: "short",
816
+ email: "invalid-email",
817
+ first_name: "John",
818
+ last_name: "Doe",
807
819
  });
808
820
  } catch (error) {
809
821
  if (error instanceof PipsendError && error.isValidationError()) {
810
- console.log('Validation failed:');
811
-
822
+ console.log("Validation failed:");
823
+
812
824
  // Access individual validation errors
813
- error.errors?.forEach(err => {
825
+ error.errors?.forEach((err) => {
814
826
  console.log(` - ${err.field}: ${err.message}`);
815
827
  });
816
-
828
+
817
829
  // Or get formatted message
818
830
  console.log(error.getDetailedMessage());
819
-
831
+
820
832
  // Output:
821
833
  // The provided data is not valid.
822
834
  // - trading_group: Trading group 'InvalidGroup' not found
@@ -831,20 +843,20 @@ try {
831
843
 
832
844
  ```typescript
833
845
  interface PipsendError {
834
- message: string; // Error message
835
- code: string; // Error code (e.g., 'VALIDATION_ERROR', 'NOT_FOUND')
836
- statusCode: number; // HTTP status code (e.g., 422, 404, 500)
837
- errors?: ValidationError[]; // Validation errors (for 422 responses)
838
- response?: any; // Full error response from server
839
-
846
+ message: string; // Error message
847
+ code: string; // Error code (e.g., 'VALIDATION_ERROR', 'NOT_FOUND')
848
+ statusCode: number; // HTTP status code (e.g., 422, 404, 500)
849
+ errors?: ValidationError[]; // Validation errors (for 422 responses)
850
+ response?: any; // Full error response from server
851
+
840
852
  // Helper methods
841
- isValidationError(): boolean; // Check if it's a validation error
842
- getDetailedMessage(): string; // Get formatted message with details
853
+ isValidationError(): boolean; // Check if it's a validation error
854
+ getDetailedMessage(): string; // Get formatted message with details
843
855
  }
844
856
 
845
857
  interface ValidationError {
846
- field: string; // Field name that failed validation
847
- message: string; // Validation error message
858
+ field: string; // Field name that failed validation
859
+ message: string; // Validation error message
848
860
  }
849
861
  ```
850
862
 
@@ -912,8 +924,8 @@ import type {
912
924
  Candle,
913
925
  Symbol,
914
926
  OpenTradeRequest,
915
- OpenTradeResponse
916
- } from '@pipsend/sdk';
927
+ OpenTradeResponse,
928
+ } from "@pipsend/sdk";
917
929
  ```
918
930
 
919
931
  ## ๐Ÿงช Testing