> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polyedge.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Node.js SDK

> Install and use the PolyEdge Node.js SDK to query trader analytics and stream live Polymarket order flow.

## Requirements

* Node.js 18 or higher
* npm

## Installation

<Steps>
  <Step title="Install the dependency">
    The SDK uses [`eventsource-client`](https://www.npmjs.com/package/eventsource-client) for SSE streaming with auto-reconnect and async iterator support.

    ```bash theme={null}
    npm install eventsource-client
    ```
  </Step>

  <Step title="Copy the SDK files">
    Download `polyedge.js` and `parser_compact_tx.js` from the [PolyEdge examples repository](https://github.com/PolyEdgeDev/polyedge-api/tree/main/examples/nodejs) and copy them into your project directory.
  </Step>
</Steps>

## Instantiation

Import `PolyEdgeClient` and pass your API key. The base URL defaults to `https://api.polyedge.dev/v1`.

```javascript theme={null}
import PolyEdgeClient from './polyedge.js';

const client = new PolyEdgeClient('your_api_key_here');
```

You can also pass a custom base URL as the second argument:

```javascript theme={null}
const client = new PolyEdgeClient('your_api_key_here', 'https://api.polyedge.dev/v1');
```

Your API key is sent on every request via the `X-PolyEdge-Key` header.

## Methods

<AccordionGroup>
  <Accordion title="getLeaderboard(params)">
    Retrieve the trader leaderboard, optionally filtered and sorted.

    ```javascript theme={null}
    const data = await client.getLeaderboard(params);
    ```

    **Parameters** — all optional:

    | Parameter           | Type   | Description                                                         |
    | ------------------- | ------ | ------------------------------------------------------------------- |
    | `limit`             | number | Number of results to return. Default: `50`, max: `100`.             |
    | `offset`            | number | Pagination offset. Default: `0`.                                    |
    | `time_frame`        | string | `'1H'`, `'4H'`, `'1D'`, `'3D'`, `'7D'`, `'30D'`. Default: `'30D'`.  |
    | `sort_by`           | string | `'pnl'`, `'roi'`, `'win_rate'`, `'market_count'`. Default: `'pnl'`. |
    | `tag`               | string | Filter by market tag, e.g. `'crypto'`, `'sports'`.                  |
    | `min_win_rate`      | number | Minimum win rate (0–100).                                           |
    | `max_win_rate`      | number | Maximum win rate (0–100).                                           |
    | `min_roi`           | number | Minimum ROI percentage.                                             |
    | `max_roi`           | number | Maximum ROI percentage.                                             |
    | `last_active_hours` | number | Only include traders active in the last N hours.                    |
    | `min_market_count`  | number | Minimum number of markets traded.                                   |
    | `max_market_count`  | number | Maximum number of markets traded.                                   |
    | `min_pnl`           | number | Minimum PnL (USDC).                                                 |

    Returns a `Promise<Object>`.
  </Accordion>

  <Accordion title="getTraderProfile(address)">
    Get a trader's detailed profile including tags, stats, and metadata.

    ```javascript theme={null}
    const data = await client.getTraderProfile('0xabc…');
    ```

    | Parameter | Type   | Description                           |
    | --------- | ------ | ------------------------------------- |
    | `address` | string | The EVM wallet address of the trader. |

    Returns a `Promise<Object>`.
  </Accordion>

  <Accordion title="getTraderMarkets(address, params)">
    Retrieve a trader's trading history aggregated by market.

    ```javascript theme={null}
    const data = await client.getTraderMarkets('0xabc…', params);
    ```

    | Parameter        | Type    | Description                                             |
    | ---------------- | ------- | ------------------------------------------------------- |
    | `address`        | string  | The EVM wallet address of the trader.                   |
    | `limit`          | number  | Number of markets to return. Default: `20`, max: `100`. |
    | `offset`         | number  | Pagination offset. Default: `0`.                        |
    | `is_active`      | boolean | Filter by active (unresolved) markets only.             |
    | `include_orders` | boolean | Include the trader's individual orders for each market. |

    Returns a `Promise<Object>`.
  </Accordion>

  <Accordion title="getTraderMarketOrders(address, marketId)">
    Retrieve a specific trader's order history within a specific market.

    ```javascript theme={null}
    const data = await client.getTraderMarketOrders('0xabc…', 12345);
    ```

    | Parameter  | Type             | Description                           |
    | ---------- | ---------------- | ------------------------------------- |
    | `address`  | string           | The EVM wallet address of the trader. |
    | `marketId` | string \| number | The specific market ID.               |

    Returns a `Promise<Object>`.
  </Accordion>

  <Accordion title="getTraderHourlyStats(address, params)">
    Get hourly aggregated performance data for a specific trader.

    ```javascript theme={null}
    const data = await client.getTraderHourlyStats('0xabc…', params);
    ```

    | Parameter | Type   | Description                                                                                  |
    | --------- | ------ | -------------------------------------------------------------------------------------------- |
    | `address` | string | The EVM wallet address of the trader.                                                        |
    | `tag`     | string | (Optional) Filter by specific market tag (e.g., `'crypto'`, `'politics'`). Default: `'all'`. |

    Returns a `Promise<Object>`.
  </Accordion>

  <Accordion title="getMarketDetail(marketId)">
    Retrieve detailed information about a specific market.

    ```javascript theme={null}
    const data = await client.getMarketDetail(12345);
    ```

    | Parameter  | Type             | Description                          |
    | ---------- | ---------------- | ------------------------------------ |
    | `marketId` | string \| number | The unique numeric ID of the market. |

    Returns a `Promise<Object>`.
  </Accordion>

  <Accordion title="streamOrders(params) — async generator">
    Subscribe to live mempool orders via SSE. Returns an async generator that yields parsed order objects.

    ```javascript theme={null}
    for await (const order of client.streamOrders(params)) {
      console.log(order);
    }
    ```

    Break out of the loop at any time — the underlying SSE connection is closed automatically in the generator's `finally` block.

    **Parameters** — all optional:

    | Parameter    | Type   | Description                                                                       |
    | ------------ | ------ | --------------------------------------------------------------------------------- |
    | `traders`    | string | Comma-separated list of trader addresses to follow.                               |
    | `tags`       | string | Comma-separated list of market tags to filter by.                                 |
    | `series`     | string | Comma-separated list of series slugs.                                             |
    | `min_usdc`   | number | Minimum USDC trade size.                                                          |
    | `max_usdc`   | number | Maximum USDC trade size.                                                          |
    | `min_shares` | number | Minimum shares amount.                                                            |
    | `max_shares` | number | Maximum shares amount.                                                            |
    | `min_price`  | number | Minimum price (0–100).                                                            |
    | `max_price`  | number | Maximum price (0–100).                                                            |
    | `format`     | string | Set to `'json'` for structured JSON. Omit for compact array format (recommended). |

    Returns `AsyncGenerator<Object, void, unknown>`.

    <Note>
      When `format` is omitted, each yielded value is the output of `parseCompactTx` — a fully structured JavaScript object. See [Compact format parsing](#compact-format-parsing) below.
    </Note>
  </Accordion>
</AccordionGroup>

## Compact format parsing

By default, `streamOrders` receives events in a compact array format optimised for low bandwidth. The `parser_compact_tx.js` utility converts each raw array into a structured object before yielding it.

The parsed object has this shape:

```javascript theme={null}
{
  txHash: string,
  timestamp: string,
  market: {
    id: string,
    question: string,
    slug: string,
    start_date: string,
    end_date: string,
    icon: string,
    neg_risk: boolean,
    event_slug: string,
    series_slug: string,
    tags: string[],
    outcome_1: string,
    outcome_2: string,
    group_item_title: string,
    event_title: string,
    event_icon: string
  },
  takerOrder: {
    side: string,       // 'BUY' or 'SELL'
    trader: {
      address: string,
      name: string,
      x_username: string,
      profile_image: string,
      profile_created_at: string
    },
    outcome: string,
    tokenId: string,
    usdc: string,       // raw 1e6 format
    shares: string,     // raw 1e6 format
    fee: string,
    feeRateBps: string
  },
  makerOrders: [ /* same shape as takerOrder */ ]
}
```

<Tip>
  USDC and shares values are returned as raw strings in 1e6 format. Divide by `1e6` to convert to human-readable amounts: `Number(order.takerOrder.usdc) / 1e6`.
</Tip>

If you prefer fully structured JSON from the API rather than parsing compact arrays yourself, pass `format: 'json'` to `streamOrders` — the raw response is yielded directly without calling the parser.

## Complete example

The following example exercises every method in the SDK, then opens the SSE stream and prints the first three events.

```javascript theme={null}
import PolyEdgeClient from './polyedge.js';

const API_KEY = 'your_api_key_here';
const client = new PolyEdgeClient(API_KEY);

function formatAmount(rawStr) {
  if (!rawStr) return "0.00";
  const num = Number(rawStr) / 1e6;
  return num.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}

async function main() {
  // 1. Get leaderboard — top 3 traders by PNL over the last 7 days
  const leaderboard = await client.getLeaderboard({ limit: 3, sort_by: 'pnl', time_frame: '7D' });
  let traderAddress = leaderboard.traders[0].profile.address;
  leaderboard.traders.forEach((t) => {
    console.log(`${t.rank}. ${t.profile.name} (${t.profile.address})`);
    console.log(`   PNL: $${formatAmount(t.total_pnl)} | ROI: ${t.roi}% | Win Rate: ${t.win_rate}%`);
  });

  // 2. Get trader profile
  const profileResponse = await client.getTraderProfile(traderAddress);
  const p = profileResponse.profile;
  console.log(`Name: ${p.name} | Address: ${p.address}`);

  // 3. Get trader markets
  const marketsResponse = await client.getTraderMarkets(traderAddress, { limit: 1 });
  const hm = marketsResponse.history[0];
  const marketId = hm.market.id;
  console.log(`Market: ${hm.market.question} (ID: ${marketId})`);

  // 4. Get trader market orders
  const ordersResponse = await client.getTraderMarketOrders(traderAddress, marketId);
  ordersResponse.orders.slice(0, 3).forEach((o, i) => {
    const price = (Number(o.price) / 1e6).toFixed(3);
    console.log(`[Order ${i + 1}] ${o.side} ${o.outcome} @ $${price}`);
  });

  // 5. Get trader hourly stats
  const hourlyResponse = await client.getTraderHourlyStats(traderAddress);
  hourlyResponse.stats.slice(0, 3).forEach((s) => {
    console.log(`Hour: ${s.hour} | PNL: $${formatAmount(s.pnl)} | Volume: $${formatAmount(s.volume)}`);
  });

  // 6. Get market detail
  const marketDetail = await client.getMarketDetail(marketId);
  const md = marketDetail.market;
  console.log(`Question: ${md.question}`);
  console.log(`Total Volume: $${formatAmount(marketDetail.total_volume)}`);

  // 7. Stream live orders — exit after 3 events
  let eventCount = 0;
  for await (const order of client.streamOrders()) {
    eventCount++;
    const taker = order.takerOrder;
    const price = taker.shares !== "0"
      ? (Number(taker.usdc) / Number(taker.shares)).toFixed(3)
      : "0.000";

    console.log(`[Event #${eventCount}] ${order.timestamp}`);
    console.log(`  Market: ${order.market.question} (${order.market.id})`);
    console.log(`  Trader: ${taker.trader?.address ?? 'Unknown'}`);
    console.log(`  Action: ${taker.side} ${taker.outcome} @ ~$${price}`);
    console.log(`  Size: ${formatAmount(taker.shares)} shares ($${formatAmount(taker.usdc)})`);

    if (eventCount >= 3) break;
  }
}

main().catch(console.error);
```
