npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pipsend/sdk

v0.3.2

Published

SDK oficial de Pipsend compatible con NodeJS y TypeScript

Readme

@pipsend/sdk

npm version License: MIT

Official Pipsend SDK for Node.js and TypeScript. Complete trading platform integration with WebSocket support.

🚀 Features

  • 6 Complete API Modules: Accounts, Orders, Positions, Trades, Market Data, Trading Groups
  • TypeScript Native with 100+ complete types
  • WebSocket Support with auto-reconnect and heartbeat
  • Advanced Filtering (dates, ranges, multi-value, search)
  • Dynamic Statistics grouped by any field
  • Pagination Support for all list endpoints
  • Dual Package (ESM + CommonJS)
  • 56 Unit Tests passing
  • Compatible with Node.js ≥16

📦 Installation

npm install @pipsend/sdk
yarn add @pipsend/sdk
pnpm add @pipsend/sdk

🔐 Authentication

The SDK uses JWT-based authentication with automatic token refresh.

import { createClient } from "@pipsend/sdk";

const client = createClient({
  server: "http://localhost:8080",
  login: "1000", // Your admin/API login
  password: "YourPassword", // Your admin/API password
});

// The SDK automatically:
// ✅ Authenticates on first API call
// ✅ Stores access and refresh tokens in memory
// ✅ Refreshes tokens automatically when they expire
// ✅ Re-authenticates if refresh fails

Authentication happens automatically - you don't need to call any login method. Just create the client and start making API calls.

Manual Authentication Control (Advanced)

If you need manual control over authentication:

// Check authentication status
const isAuthenticated = client.isAuthenticated();

// Manually refresh token
await client.refreshToken();

// Logout (clears tokens)
await client.logout();

// Get current token info
const tokenInfo = client.getTokenInfo();
console.log("Token expires at:", tokenInfo?.expiresAt);

🔧 Quick Start

import { createClient } from "@pipsend/sdk";

// Create authenticated client
const client = createClient({
  server: "http://localhost:8080",
  login: "1000",
  password: "DemoMaster",
});

const login = 50001;

// List accounts with filters
const accounts = await client.accounts.list({
  state: "active",
  country: "Mexico",
  min_balance: 1000,
});

// Open a trade
const trade = await client.trades.open({
  login,
  symbol: "EURUSD",
  action: "buy",
  type: "market",
  volume: 1.0,
  stop_loss: 1.085,
  take_profit: 1.095,
});

// Get market data
const candles = await client.marketData.getCandles({
  symbol: "BTCUSD",
  timeframe: "1h",
  limit: 100,
});

// WebSocket real-time updates
client.stream.onPriceUpdate((price) => {
  console.log("Price update:", price);
});

await client.stream.connect();

📚 API Modules

1. Accounts API

Manage accounts with advanced filtering and statistics.

// Create a new trading account
const newAccount = await client.accounts.create({
  trading_group: "Premium",
  country: "MX",
  master_password: "SecurePass123!",
  investor_password: "InvestorPass123!",
  email: "[email protected]",
  first_name: "John",
  last_name: "Doe",
  leverage: 100,
  state: "active",
});

// List accounts with filters
const accounts = await client.accounts.list({
  state: "active",
  country: "Mexico,United States",
  trading_group: "Premium",
  min_balance: 1000,
  max_balance: 50000,
  page: 1,
  per_page: 20,
});

// Get statistics with filters
const stats = await client.accounts.getStatistics({
  country: "Mexico",
  state: "active",
});

// Get all account logins
const logins = await client.accounts.getLogins();

// Get account status/metrics (balance, equity, credit, margin)
const status = await client.accounts.getStatus(50001);
console.log("Balance:", status.data.balance);
console.log("Equity:", status.data.equity);
console.log("Credit:", status.data.credit);
console.log("Margin:", status.data.margin);

// Change passwords (master and/or investor)
await client.accounts.changePassword(50001, {
  master: "NewMasterPass123!",
  investor: "NewInvestorPass123!",
});

// Archive/Unarchive
await client.accounts.archive(50001);
await client.accounts.unarchive(50001);

// Update account information (partial update)
await client.accounts.update(50001, {
  email: "[email protected]",
  leverage: 200,
  city: "Los Angeles",
  trading_group: "Premium",
});

// Adjust balance or credit
await client.accounts.balance(50001, {
  type: "balance",
  amount: 500.0,
  comment: "Client deposit",
});

await client.accounts.balance(50001, {
  type: "credit",
  amount: 1000.0,
  comment: "Credit line increase",
});

// Subtract balance
await client.accounts.balance(50001, {
  type: "balance",
  amount: -200.0,
  comment: "Withdrawal request",
});

2. Orders API

Manage pending orders with statistics and validation.

// List orders with advanced filters
const orders = await client.orders.list({
  login: "50001",
  symbol: "EURUSD,GBPUSD",
  order_type: "limit",
  status: "new,partial",
  created_from: "2025-01-01T00:00:00Z",
  created_to: "2025-01-31T23:59:59Z",
  price_min: 1.08,
  price_max: 1.1,
  sort_by: "created_at",
  sort_order: "desc",
});

// Get statistics grouped by symbol
const stats = await client.orders.getStats({
  login: "50001",
  group_by: "symbol",
});

// Get totals by order type
const totals = await client.orders.getTotals({
  login: "50001",
  group_by: "order_type",
});

// Update order
await client.orders.update(12345, {
  login: 50001,
  stop_loss: 1.08,
  take_profit: 1.095,
});

// Delete order
await client.orders.delete(12345, { login: 50001 });

// Validate orders
const checkResult = await client.orders.check({
  filters: {
    logins: [50001],
    statuses: ["new"],
  },
});

3. Positions API

Manage open positions with recalculation support.

// List positions with filters
const positions = await client.positions.list({
  login: "50001",
  symbol: "EURUSD",
  state: "open",
  profit_min: 100,
  profit_max: 1000,
});

// Get statistics grouped by type
const stats = await client.positions.getStats({
  login: "50001",
  state: "open",
  group_by: "type",
});

// Get totals by symbol
const totals = await client.positions.getTotals({
  login: "50001",
  group_by: "symbol",
});

// Update position
await client.positions.update(1, {
  login: 50001,
  stop_loss: 1.0875,
  take_profit: 1.0975,
});

// Delete position
await client.positions.delete(1, { login: 50001 });

// Recalculate positions
const checkResult = await client.positions.check({
  filters: {
    logins: [50001],
    states: ["open"],
  },
});

4. Trades API

Execute trading operations with margin checking.

// Check margin before trading
const marginCheck = await client.trades.checkMargin({
  login: 50001,
  symbol: "EURUSD",
  action: "buy",
  volume: 1.0,
});

if (marginCheck.can_execute) {
  // Open trade
  const trade = await client.trades.open({
    login: 50001,
    symbol: "EURUSD",
    action: "buy",
    type: "market",
    volume: 1.0,
    stop_loss: 1.085,
    take_profit: 1.095,
    comment: "API Trade",
  });

  // Modify trade
  await client.trades.modify({
    login: 50001,
    position_id: trade.position_id,
    stop_loss: 1.0875,
    take_profit: 1.0975,
  });

  // Calculate potential profit
  const profitCalc = await client.trades.calculateProfit({
    login: 50001,
    symbol: "EURUSD",
    action: "buy",
    volume: 1.0,
    open_price: 1.09,
    close_price: 1.095,
  });

  // Close trade (partial or full)
  await client.trades.close({
    login: 50001,
    position_id: trade.position_id,
    volume: 0.5, // Partial close
    comment: "Taking profit",
  });
}

// Force price (for historical data import)
const historicalTrade = await client.trades.open({
  login: 50001,
  symbol: "EURUSD",
  action: "buy",
  type: "market",
  volume: 1.0,
  price: 1.085,
  force_price: true,
  force_timestamp: "2025-01-15T10:30:00Z",
});

5. Market Data API

Query historical market data (minimum 1 hour old).

// Get candles with filters
const candles = await client.marketData.getCandles({
  symbol: "BTCUSD,ETHUSD",
  timeframe: "1h",
  from: "2025-01-01T00:00:00Z",
  to: "2025-01-02T00:00:00Z",
  min_volume: 1000,
  max_volume: 50000,
  sort: "volume",
  order: "desc",
  limit: 100,
});

// Get last 100 candles
const recentCandles = await client.marketData.getCandles({
  symbol: "BTCUSD",
  timeframe: "1m",
  limit: 100,
  order: "desc",
});

// Get symbols with filters
const symbols = await client.marketData.getSymbols({
  group: "CRYPTO_MAJOR",
  has_data: true,
  search: "bitcoin",
});

// Get groups hierarchy
const groups = await client.marketData.getGroups({
  root_only: true,
  sort: "symbol_count",
  order: "desc",
});

Timeframes: 1m, 5m, 15m, 1h, 4h, 1d

Note: Data must be at least 1 hour old (no real-time data).

6. Trading Groups API

Manage trading groups and their statistics.

// List trading groups
const groups = await client.tradingGroups.list({
  page: 1,
  per_page: 20,
});

// Get statistics
const stats = await client.tradingGroups.getStatistics();

7. WebSocket API

Real-time updates for positions and balance with manual channel subscription.

// Enable WebSocket in config
const client = createClient({
  server: "http://localhost:8080",
  login: "1000",
  password: "DemoMaster",
  websocket: {
    enabled: true,
    autoConnect: false,
  },
});

// Connect to WebSocket
await client.stream.connect();

// Subscribe to channels
client.stream.subscribe([
  "positions:new", // New positions opened
  "positions:closed", // Positions closed (total and partial)
  "positions:updated", // Position PnL updates (throttled to 1 per 2s)
  "accounts:balance", // Balance updates
]);

// Listen to position opened events
client.stream.onPositionOpened((event) => {
  const pos = event.position;
  console.log(
    "Position opened:",
    pos.symbol,
    pos.side === 1 ? "LONG" : "SHORT",
    pos.qty,
  );
});

// Listen to position closed events
client.stream.onPositionClosed((event) => {
  const pos = event.position;
  console.log("Position closed:", pos.symbol, "PnL:", pos.net_pnl);
});

// Listen to position updated events (throttled)
client.stream.onPositionUpdated((event) => {
  const pos = event.position;
  console.log("Position update:", pos.position_id, "PnL:", pos.unrealized_pnl);
});

// Listen to balance updates
client.stream.onBalanceUpdated((event) => {
  console.log("Balance:", event.balance, "Equity:", event.equity);
});

// Unsubscribe from channels
client.stream.unsubscribe(["positions:updated"]);

// Disconnect
client.stream.disconnect();

Available Channels:

  • positions:new - New position opened
  • positions:closed - Position closed (total or partial)
  • positions:updated - PnL updates (throttled to max 1 per 2 seconds)
  • accounts:balance - Balance changes

Features:

  • Manual subscription to specific channels
  • Auto-reconnect with exponential backoff
  • Heartbeat/ping-pong mechanism
  • Automatic subscription restoration on reconnect
  • Throttled position updates to reduce load

See WebSocket API Documentation for complete guide.

� Documentation

�🔧 Configuration

Basic Configuration

const client = createClient({
  server: "http://localhost:8080", // Required: API server URL
  login: "1000", // Required: Admin/API login
  password: "YourPassword", // Required: Admin/API password
});

Advanced Configuration

const client = createClient({
  server: "http://localhost:8080",
  login: "1000",
  password: "YourPassword",

  // WebSocket configuration (optional)
  websocket: {
    enabled: true, // Enable WebSocket support
    autoConnect: false, // Auto-connect on client creation
    autoReconnect: true, // Auto-reconnect on disconnect
    maxReconnectAttempts: 5, // Max reconnection attempts
    heartbeatInterval: 30000, // Heartbeat interval in ms
  },
});

Configuration Options

| Option | Type | Required | Default | Description | | -------------------------------- | ------- | -------- | ------- | ---------------------------------- | | server | string | ✅ Yes | - | Pipsend API server URL | | login | string | ✅ Yes | - | Admin/API login for authentication | | password | string | ✅ Yes | - | Admin/API password | | websocket.enabled | boolean | No | false | Enable WebSocket support | | websocket.autoConnect | boolean | No | false | Auto-connect on creation | | websocket.autoReconnect | boolean | No | true | Auto-reconnect on disconnect | | websocket.maxReconnectAttempts | number | No | 5 | Max reconnection attempts | | websocket.heartbeatInterval | number | No | 30000 | Heartbeat interval (ms) |

📦 API Response Structure

All API endpoints return a consistent response structure:

Success Response (without pagination)

{
  status: "success",
  status_code: "SUCCESS",
  data: [...] // Array of results or single object
}

Success Response (with pagination)

{
  status: "success",
  status_code: "SUCCESS",
  data: [...],
  meta: {
    total: 156,
    page: 1,
    per_page: 20,
    total_pages: 8,
    has_next: true,
    has_prev: false
  }
}

Error Response

{
  status: "error",
  status_code: "VALIDATION_ERROR",
  message: "The provided data is not valid.",
  errors?: [
    {
      field: "symbol",
      message: "At least one symbol is required."
    }
  ]
}

Common Status Codes

Success:

  • SUCCESS - Operation successful
  • CREATED - Resource created successfully

Errors:

  • VALIDATION_ERROR (400) - Invalid parameters
  • BAD_REQUEST (400) - Invalid request
  • UNAUTHORIZED (401) - Authentication required
  • FORBIDDEN (403) - Insufficient permissions
  • NOT_FOUND (404) - Resource not found
  • CONFLICT (409) - Resource conflict (duplicate)
  • INTERNAL_ERROR (500) - Server error

Market Data Specific:

  • SYMBOL_NOT_FOUND (404) - Symbol not found
  • INVALID_TIMEFRAME (400) - Invalid timeframe
  • TIME_RANGE_TOO_LARGE (400) - Time range exceeds maximum
  • DATA_TOO_RECENT (400) - Data must be at least 1 hour old

🎯 Common Patterns

Pagination

Option 1: Get all results (no pagination)

// Returns all results in a single array
const accounts = await client.accounts.list({
  state: "active",
});
// Response: { status, status_code, data: [...] }

Option 2: Paginated results

// Returns paginated results with metadata
const accounts = await client.accounts.list({
  state: "active",
  page: 1,
  per_page: 20,
});
// Response: { status, status_code, data: [...], meta: {...} }

// Iterate through pages
let page = 1;
let hasMore = true;

while (hasMore) {
  const response = await client.accounts.list({
    state: "active",
    page,
    per_page: 50,
  });

  // Process response.data
  console.log(`Page ${page}:`, response.data.length);

  hasMore = response.meta.has_next;
  page++;
}

Option 3: Limit results (ignores pagination)

// Get specific number of results
const candles = await client.marketData.getCandles({
  symbol: "BTCUSD",
  timeframe: "1h",
  limit: 100, // Max: 10,000 for candles
});

Multi-value Filters

Many filters accept comma-separated values:

// Multiple symbols (OR logic)
const positions = await client.positions.list({
  symbol: "EURUSD,GBPUSD,USDJPY", // Positions in ANY of these symbols
});

// Multiple countries
const accounts = await client.accounts.list({
  country: "Mexico,United States,Canada",
});

// Multiple states
const orders = await client.orders.list({
  status: "new,partial", // Orders with status new OR partial
});

Date Filters

All date parameters must be in ISO 8601 / RFC3339 format (UTC):

// Correct format
const positions = await client.positions.list({
  opened_from: "2025-01-01T00:00:00Z",
  opened_to: "2025-01-31T23:59:59Z",
});

// Also valid
const candles = await client.marketData.getCandles({
  symbol: "BTCUSD",
  timeframe: "1h",
  from: "2025-01-15T10:30:00Z",
  to: "2025-01-15T18:30:00Z",
});

Note: Market data has a minimum age of 1 hour. The to parameter cannot be more recent than now - 1 hour.

Range Filters

Use min_* and max_* for numeric ranges:

// Balance range
const accounts = await client.accounts.list({
  min_balance: 1000,
  max_balance: 50000,
});

// Profit range
const positions = await client.positions.list({
  profit_min: 100,
  profit_max: 1000,
});

// Volume range
const candles = await client.marketData.getCandles({
  symbol: "BTCUSD",
  timeframe: "1h",
  min_volume: 1000,
  max_volume: 50000,
});

Sorting

Most list endpoints support sorting:

const orders = await client.orders.list({
  login: "50001",
  sort_by: "created_at", // Field to sort by
  sort_order: "desc", // 'asc' or 'desc'
});

const candles = await client.marketData.getCandles({
  symbol: "BTCUSD",
  timeframe: "1h",
  sort: "volume", // Some endpoints use 'sort'
  order: "desc", // instead of 'sort_by'/'sort_order'
});

⚠️ Error Handling

All errors thrown by the SDK are instances of PipsendError with detailed information.

Basic Error Handling

import { PipsendError } from "@pipsend/sdk";

try {
  const trade = await client.trades.open({
    login: 50001,
    symbol: "EURUSD",
    action: "buy",
    type: "market",
    volume: 1.0,
  });

  console.log("Trade opened:", trade.position_id);
} catch (error) {
  if (error instanceof PipsendError) {
    console.error("Error code:", error.code);
    console.error("Status code:", error.statusCode);
    console.error("Message:", error.message);

    // Check if it's a validation error
    if (error.isValidationError()) {
      console.error("Validation errors:", error.errors);
      // Get formatted message with all details
      console.error(error.getDetailedMessage());
    }
  }
}

Handling Validation Errors (422)

When the API returns validation errors, the SDK provides detailed field-level information:

try {
  const account = await client.accounts.create({
    trading_group: "InvalidGroup",
    country: "XYZ",
    master_password: "short",
    investor_password: "short",
    email: "invalid-email",
    first_name: "John",
    last_name: "Doe",
  });
} catch (error) {
  if (error instanceof PipsendError && error.isValidationError()) {
    console.log("Validation failed:");

    // Access individual validation errors
    error.errors?.forEach((err) => {
      console.log(`  - ${err.field}: ${err.message}`);
    });

    // Or get formatted message
    console.log(error.getDetailedMessage());

    // Output:
    // The provided data is not valid.
    //   - trading_group: Trading group 'InvalidGroup' not found
    //   - country: Country 'XYZ' not found
    //   - master_password: The field master_password must be at least 8 characters.
    //   - email: The field email must be a valid email address.
  }
}

Error Properties

interface PipsendError {
  message: string; // Error message
  code: string; // Error code (e.g., 'VALIDATION_ERROR', 'NOT_FOUND')
  statusCode: number; // HTTP status code (e.g., 422, 404, 500)
  errors?: ValidationError[]; // Validation errors (for 422 responses)
  response?: any; // Full error response from server

  // Helper methods
  isValidationError(): boolean; // Check if it's a validation error
  getDetailedMessage(): string; // Get formatted message with details
}

interface ValidationError {
  field: string; // Field name that failed validation
  message: string; // Validation error message
}

Common Error Scenarios

// 1. Insufficient margin
try {
  await client.trades.open({...});
} catch (error: any) {
  if (error.status_code === 'INSUFFICIENT_MARGIN') {
    // Check margin first
    const check = await client.trades.checkMargin({...});
    console.log('Required margin:', check.margin_required);
  }
}

// 2. Position not found
try {
  await client.positions.update(999, {...});
} catch (error: any) {
  if (error.status_code === 'NOT_FOUND') {
    console.error('Position does not exist');
  }
}

// 3. Invalid time range
try {
  await client.marketData.getCandles({
    symbol: 'BTCUSD',
    timeframe: '1m',
    from: '2025-01-01T00:00:00Z',
    to: '2025-02-01T00:00:00Z'  // Too large for 1m
  });
} catch (error: any) {
  if (error.status_code === 'TIME_RANGE_TOO_LARGE') {
    console.error('Time range exceeds maximum for this timeframe');
    // Max ranges: 1m=7d, 5m=30d, 15m=60d, 1h=6mo, 4h=1y, 1d=5y
  }
}

// 4. Data too recent
try {
  await client.marketData.getCandles({
    symbol: 'BTCUSD',
    timeframe: '1h',
    to: new Date().toISOString()  // Too recent!
  });
} catch (error: any) {
  if (error.status_code === 'DATA_TOO_RECENT') {
    console.error('Market data must be at least 1 hour old');
  }
}

📝 TypeScript Support

The SDK is written in TypeScript and provides complete type definitions:

import type {
  Account,
  Order,
  Position,
  Candle,
  Symbol,
  OpenTradeRequest,
  OpenTradeResponse,
} from "@pipsend/sdk";

🧪 Testing

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Type checking
npm run typecheck

# Linting
npm run lint

🛠️ Development

# Install dependencies
npm install

# Build
npm run build

# Watch mode
npm run dev

📖 Examples

Check the examples/ directory for complete usage examples:

  • examples/api-usage.ts - Comprehensive API usage
  • examples/quick-start.ts - Quick start guide

🔗 Links

📄 License

MIT © 2025 Pipsend

🤝 Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

⚠️ Project Status

Current Version: 0.1.0 (Beta)

This SDK is in active development. The API may change between minor versions until version 1.0.0.

🌟 Features Roadmap

  • [ ] Authentication with JWT tokens
  • [ ] Rate limiting handling
  • [ ] Retry logic with exponential backoff
  • [ ] Request/response interceptors
  • [ ] Batch operations
  • [ ] Streaming data export
  • [ ] Advanced error handling
  • [ ] Performance metrics
  • [ ] Request caching
  • [ ] GraphQL support (future)

📊 Stats

  • 6 API Modules: Accounts, Orders, Positions, Trades, Market Data, Trading Groups
  • 100+ TypeScript Types: Fully typed interfaces
  • 56 Unit Tests: Comprehensive test coverage
  • Bundle Size: ~26 KB (minified)
  • Zero Dependencies: Lightweight and fast