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

# Wallet Trades Stream

> Every trade of the wallets you follow, pushed as it lands: one wallet or a list of up to 100 per subscription. Events carry the same fields as REST /v1/wallet/trades, plus the wallet.

`WS channel: wallet-trades`

Enabled on your key on request: contact us.

Every trade of the wallets you follow, pushed as it lands: one wallet or a list of up to 100 per subscription. Events carry the same fields as REST [`/v1/wallet/trades`](/endpoints/wallet-trades), plus the `wallet`.

Use it for copy trading, wallet trackers and alerts. For the positions of a wallet kept up to date, see the [Wallet Positions Stream](/streams/wallet-positions-stream); for their live value and PnL, the [Wallet Portfolio Stream](/streams/wallet-portfolio-stream).

## Delivery model

* **Events, as they land.** There is no snapshot: the stream starts with the first trade that follows your subscription. Past trades are on REST.
* **One event per transaction, token and side.** A routed swap never doubles volumes: same rule as REST. Routed intermediate legs are delivered and flagged `isRoutingHop`, so you choose to show or skip them.
* **One wallet on one chain per entry.** A wallet followed on two chains is two entries.

## Parameters

Give either `chain` and `address`, or `wallets`.

<ParamField body="chain" type="string">
  Public chain id, `evm:<id>` or `solana`. Required with `address`. Example: `solana`
</ParamField>

<ParamField body="address" type="string">
  The wallet address (EVM hex, case-insensitive; Solana base58). Example: `DfMxre4cKmvogbLrPigxmibVTTQDuzjdXojWzjCXXhzj`
</ParamField>

<ParamField body="wallets" type="object[]">
  A list of 1 to 100 wallets, `[{ "chain": "...", "address": "..." }, ...]`, in place of `chain` and `address`. Each wallet counts as one subscription in the limit of your account. With a list, every message is `"data": [trade, ...]`.
</ParamField>

<ParamField body="updatePeriod" type="integer">
  Milliseconds, 0 to 60000, default `0` (every trade as it lands). Above 0, one message per period carries every trade of the period in order, as `"data": [trade, ...]`, for 1 credit. The ack carries the value applied (snapped up to `0, 100, 250, 500, 1000, 2000, 5000, 10000, 30000, 60000`). See [Choosing your pace](/streams/overview#choosing-your-pace-updateperiod).
</ParamField>

## The trade

| Field | |
| - | - |
| `wallet` | The wallet that traded |
| `id` | Stable id of the trade: dedupe on it |
| `at` | Time of the trade, ms |
| `chain`, `tokenAddress`, `poolAddress` | Where it happened |
| `isBuy` | `true` when the wallet bought the token |
| `amountToken`, `priceNative`, `volumeNative`, `volumeUsd` | Size and price. `volumeUsd` is `null` when the USD rate is unknown, never `0` |
| `feesNative` | Transaction fees, in the native asset |
| `isWash` | Boolean on Solana, `null` on EVM |
| `isRoutingHop` | `true` for an intermediate leg of a routed swap |
| `txHash`, `block`, `logIndex` | The transaction (signature and slot on Solana) |

## Resume

With a single wallet, every event carries a `cursor`. After a reconnect, subscribe again with `"since": "<cursor of the last event you received>"`: you receive every trade after it (up to 5 minutes back), then live. Trades you may already have are flagged `"replay": true`: dedupe them by `data.id`. If the replay is not available, a `REPLAY_TOO_OLD` notice gives `details.restFromMs`: fetch [`/v1/wallet/trades`](/endpoints/wallet-trades) back to there, the subscription keeps going.

A list subscription takes no `since`: after a reconnect, subscribe again and read REST for each wallet over the time you were away. See [Reconnect & resume](/streams/overview#reconnect--resume).

## Billing

**1 credit per message delivered**: one trade, or one batch of trades. A wallet that does not trade costs nothing, and the connection is free.

`GET /v1/usage/breakdown` reports this channel under `WS wallet-trades`, where `requests` is the number of messages delivered.

## Errors

| Code | Meaning | What to do |
| - | - | - |
| `INVALID_PARAM` | A parameter was refused. `details.param` names it (`chain`, `address`, `wallets[3].address`, `since`) | Fix the subscription |
| `INVALID_CHAIN` | Unknown chain id | Fix the subscription |
| `RATE_LIMITED` | The subscription limit of your account is reached, or the list does not fit in what is left | Close subscriptions, send a shorter list, or ask us to raise the limit |
| `UPSTREAM_ERROR` with `details.retryAfterMs` | Wallet streams are starting | Send the same `subscribe` again after `details.retryAfterMs` |
| `UPSTREAM_ERROR` with `details.resumes: true` | Live data is temporarily unavailable | Nothing: the subscription resumes by itself |

## Close codes

| Code | Meaning |
| - | - |
| `4401` | Auth - key missing, invalid, or revoked. Live connections are dropped the moment a key is revoked. |
| `4402` | Monthly credit quota exhausted (the WebSocket mirror of REST `402`). |
| `1012` | Server restart - reconnect after the `retryAfterMs` of the JSON reason, then subscribe again. |
| `1013` | Server at capacity - reconnect after the `retryAfterMs` of the JSON reason. |
| `1008` | Policy - subscription limits, flooding, or a blocked socket. Fix the cause before reconnecting. |
| `1001` | Idle timeout - no `ping` within the keepalive window. |

<RequestExample>
  ```json Subscribe (one wallet) theme={null}
  {
    "op": "subscribe",
    "channel": "wallet-trades",
    "id": "whale-1",
    "params": {
      "chain": "solana",
      "address": "DfMxre4cKmvogbLrPigxmibVTTQDuzjdXojWzjCXXhzj"
    }
  }
  ```

  ```json Subscribe (a list) theme={null}
  {
    "op": "subscribe",
    "channel": "wallet-trades",
    "id": "followed",
    "params": {
      "wallets": [
        { "chain": "solana", "address": "DfMxre4cKmvogbLrPigxmibVTTQDuzjdXojWzjCXXhzj" },
        { "chain": "evm:8453", "address": "0x95d955179a7cd45aeef394ed39f6a8d8b1bd1e09" }
      ]
    }
  }
  ```
</RequestExample>

<ResponseExample>
  ```json Ack theme={null}
  {
    "op": "subscribed",
    "id": "whale-1",
    "channel": "wallet-trades",
    "updatePeriod": 0
  }
  ```

  ```json Trade (one wallet) theme={null}
  {
    "op": "event",
    "id": "whale-1",
    "channel": "wallet-trades",
    "data": {
      "wallet": "DfMxre4cKmvogbLrPigxmibVTTQDuzjdXojWzjCXXhzj",
      "id": "5hG8mJ3tX1qYw2Zk9uVb7nRc4pLs6dEa8fTy1oWq3xNv2KjH9gBm5rCz7eUi4sPa6tDl8yFo1wXn3vQk5jMh:CBZq5ycLcr6mnYvjFTPuYSuhgS3ujsiTrT4sqatBpump:b",
      "at": 1790539767000,
      "chain": "solana",
      "tokenAddress": "CBZq5ycLcr6mnYvjFTPuYSuhgS3ujsiTrT4sqatBpump",
      "poolAddress": "Ea5SjE2Y6yvCeW5dYTn7PYMuW5ikXkvbGdcmSnXeaLjS",
      "isBuy": true,
      "amountToken": 15915963.2,
      "priceNative": 3.1415e-8,
      "volumeNative": 0.5,
      "volumeUsd": 75.02,
      "feesNative": 0.000105,
      "isWash": false,
      "isRoutingHop": false,
      "txHash": "5hG8mJ3tX1qYw2Zk9uVb7nRc4pLs6dEa8fTy1oWq3xNv2KjH9gBm5rCz7eUi4sPa6tDl8yFo1wXn3vQk5jMh",
      "block": 371204455,
      "logIndex": 0
    },
    "asOf": 1790539767412,
    "cursor": "v1.amun6v2l5lbes.2kx.mfq3c2y2"
  }
  ```

  ```json Trades (a list) theme={null}
  {
    "op": "event",
    "id": "followed",
    "channel": "wallet-trades",
    "data": [
      {
        "wallet": "0x95d955179a7cd45aeef394ed39f6a8d8b1bd1e09",
        "id": "0x9d6dd98095ebcb254576b23b2269edf8fa984b581404209aa2a5fe3a14431bdf:289",
        "at": 1790539768000,
        "chain": "evm:8453",
        "tokenAddress": "0xb2000000000000000000007bf6d5cbb0e24cb301",
        "poolAddress": "0x0ca6485b7e9cf814a3fd09d81672b07323535b64",
        "isBuy": true,
        "amountToken": 77.05662024406023,
        "priceNative": 5.4747124708872e-7,
        "volumeNative": 0.000042612402192036,
        "volumeUsd": 0.08021081608014609,
        "feesNative": 0.000000841192,
        "isWash": null,
        "isRoutingHop": false,
        "txHash": "0x9d6dd98095ebcb254576b23b2269edf8fa984b581404209aa2a5fe3a14431bdf",
        "block": 49964744,
        "logIndex": 289
      }
    ],
    "asOf": 1790539768301
  }
  ```
</ResponseExample>


## AsyncAPI

````yaml asyncapi.json wallet-trades
id: wallet-trades
title: Wallet Trades Stream
description: >-
  Every trade of the wallets you follow, pushed as it lands: one wallet or a
  list of up to 100 per subscription. No snapshot: the stream starts with the
  first trade after your subscription. Events carry the fields of REST
  `/v1/wallet/trades`, plus the `wallet`. Enabled on your key on request.
servers:
  - id: production
    protocol: wss
    host: ws.serialized.xyz
    bindings: []
    variables: []
address: wallet-trades
parameters: []
bindings: []
operations:
  - &ref_2
    id: subscribe-wallet-trades
    title: Subscribe Wallet Trades Stream
    type: send
    messages:
      - &ref_5
        id: subscribe
        payload:
          - name: Subscribe
            description: Client frame opening the subscription (additive, ack is explicit).
            type: object
            properties:
              - name: op
                type: string
                description: subscribe
                required: true
              - name: channel
                type: string
                description: wallet-trades
                required: true
              - name: id
                type: string
                description: >-
                  Client-chosen subscription id, echoed on every frame of this
                  subscription.
                required: true
              - name: params
                type: object
                required: true
                properties:
                  - name: chain
                    type: string
                    description: >-
                      Public chain id, `evm:<id>` or `solana`. Required with
                      `address`.
                    required: false
                  - name: address
                    type: string
                    description: The wallet address. Required unless you give `wallets`.
                    required: false
                  - name: wallets
                    type: array
                    description: >-
                      A list of 1 to 100 wallets in place of `chain` and
                      `address`; each counts as one subscription, every message
                      is then `"data": [trade, ...]`. `since` is not available
                      on a list.
                    required: false
                    properties:
                      - name: chain
                        type: string
                        required: true
                      - name: address
                        type: string
                        required: true
                  - name: updatePeriod
                    type: integer
                    description: >-
                      Milliseconds, 0 to 60000, default 0: how often, at most,
                      this subscription receives a message (snapped up to 0,
                      100, 250, 500, 1000, 2000, 5000, 10000, 30000, 60000; the
                      ack carries the value applied). Above 0, one message per
                      period carries every trade of the period as `"data":
                      [trade, ...]`.
                    required: false
              - name: since
                type: string
                description: >-
                  Optional, next to `params`: the `cursor` of the last event you
                  received. You get the deltas you missed, or a snapshot of the
                  current view.
                required: false
        headers: []
        jsonPayloadSchema:
          type: object
          properties:
            op:
              type: string
              const: subscribe
              x-parser-schema-id: <anonymous-schema-124>
            channel:
              type: string
              const: wallet-trades
              x-parser-schema-id: <anonymous-schema-125>
            id:
              type: string
              description: >-
                Client-chosen subscription id, echoed on every frame of this
                subscription.
              x-parser-schema-id: <anonymous-schema-126>
            params:
              type: object
              properties:
                chain:
                  type: string
                  description: >-
                    Public chain id, `evm:<id>` or `solana`. Required with
                    `address`.
                  x-parser-schema-id: <anonymous-schema-128>
                address:
                  type: string
                  description: The wallet address. Required unless you give `wallets`.
                  x-parser-schema-id: <anonymous-schema-129>
                wallets:
                  type: array
                  minItems: 1
                  maxItems: 100
                  items:
                    type: object
                    properties:
                      chain:
                        type: string
                        x-parser-schema-id: <anonymous-schema-132>
                      address:
                        type: string
                        x-parser-schema-id: <anonymous-schema-133>
                    required:
                      - chain
                      - address
                    x-parser-schema-id: <anonymous-schema-131>
                  description: >-
                    A list of 1 to 100 wallets in place of `chain` and
                    `address`; each counts as one subscription, every message is
                    then `"data": [trade, ...]`. `since` is not available on a
                    list.
                  x-parser-schema-id: <anonymous-schema-130>
                updatePeriod:
                  type: integer
                  minimum: 0
                  maximum: 60000
                  default: 0
                  description: >-
                    Milliseconds, 0 to 60000, default 0: how often, at most,
                    this subscription receives a message (snapped up to 0, 100,
                    250, 500, 1000, 2000, 5000, 10000, 30000, 60000; the ack
                    carries the value applied). Above 0, one message per period
                    carries every trade of the period as `"data": [trade, ...]`.
                  x-parser-schema-id: <anonymous-schema-134>
              x-parser-schema-id: <anonymous-schema-127>
            since:
              type: string
              description: >-
                Optional, next to `params`: the `cursor` of the last event you
                received. You get the deltas you missed, or a snapshot of the
                current view.
              x-parser-schema-id: <anonymous-schema-135>
          required:
            - op
            - channel
            - id
            - params
          x-parser-schema-id: <anonymous-schema-123>
        title: Subscribe
        description: Client frame opening the subscription (additive, ack is explicit).
        example: |-
          {
            "op": "subscribe",
            "channel": "wallet-trades",
            "id": "whale-1",
            "params": {
              "chain": "solana",
              "address": "DfMxre4cKmvogbLrPigxmibVTTQDuzjdXojWzjCXXhzj"
            }
          }
        bindings: []
        extensions:
          - id: x-parser-unique-object-id
            value: subscribe
          - id: x-parser-message-name
            value: subscribe
    bindings: []
    extensions: &ref_0
      - id: x-parser-unique-object-id
        value: wallet-trades
  - &ref_1
    id: receive-wallet-trades
    title: Wallet Trades Stream frames
    type: receive
    messages:
      - &ref_3
        id: ack
        payload:
          - name: Ack
            description: 'Server acknowledgement: the subscription is live.'
            type: object
            properties:
              - name: type
                type: string
                description: object
                required: false
        headers: []
        jsonPayloadSchema:
          type: object
          x-parser-schema-id: <anonymous-schema-136>
        title: Ack
        description: 'Server acknowledgement: the subscription is live.'
        example: |-
          {
            "op": "subscribed",
            "id": "whale-1",
            "channel": "wallet-trades",
            "updatePeriod": 0
          }
        bindings: []
        extensions:
          - id: x-parser-unique-object-id
            value: ack
          - id: x-parser-message-name
            value: ack
      - &ref_4
        id: trade
        payload:
          - name: Trade
            description: >-
              Server push frame, one per trade of a followed wallet (a batch per
              period with `updatePeriod`): 1 credit per message.
            type: object
            properties:
              - name: type
                type: string
                description: object
                required: false
              - name: description
                type: string
                description: >-
                  `data` is the REST `/v1/wallet/trades` trade plus `wallet`;
                  `cursor` resumes a single-wallet subscription; `"replay":
                  true` flags a trade you may already have.
                required: false
        headers: []
        jsonPayloadSchema:
          type: object
          description: >-
            `data` is the REST `/v1/wallet/trades` trade plus `wallet`; `cursor`
            resumes a single-wallet subscription; `"replay": true` flags a trade
            you may already have.
          x-parser-schema-id: <anonymous-schema-137>
        title: Trade
        description: >-
          Server push frame, one per trade of a followed wallet (a batch per
          period with `updatePeriod`): 1 credit per message.
        example: |-
          {
            "op": "event",
            "id": "whale-1",
            "channel": "wallet-trades",
            "data": {
              "wallet": "DfMxre4cKmvogbLrPigxmibVTTQDuzjdXojWzjCXXhzj",
              "id": "5hG8mJ3tX1qYw2Zk9uVb7nRc4pLs6dEa8fTy1oWq3xNv2KjH9gBm5rCz7eUi4sPa6tDl8yFo1wXn3vQk5jMh:CBZq5ycLcr6mnYvjFTPuYSuhgS3ujsiTrT4sqatBpump:b",
              "at": 1790539767000,
              "chain": "solana",
              "tokenAddress": "CBZq5ycLcr6mnYvjFTPuYSuhgS3ujsiTrT4sqatBpump",
              "poolAddress": "Ea5SjE2Y6yvCeW5dYTn7PYMuW5ikXkvbGdcmSnXeaLjS",
              "isBuy": true,
              "amountToken": 15915963.2,
              "priceNative": 3.1415e-8,
              "volumeNative": 0.5,
              "volumeUsd": 75.02,
              "feesNative": 0.000105,
              "isWash": false,
              "isRoutingHop": false,
              "txHash": "5hG8mJ3tX1qYw2Zk9uVb7nRc4pLs6dEa8fTy1oWq3xNv2KjH9gBm5rCz7eUi4sPa6tDl8yFo1wXn3vQk5jMh",
              "block": 371204455,
              "logIndex": 0
            },
            "asOf": 1790539767412,
            "cursor": "v1.amun6v2l5lbes.2kx.mfq3c2y2"
          }
        bindings: []
        extensions:
          - id: x-parser-unique-object-id
            value: trade
          - id: x-parser-message-name
            value: trade
    bindings: []
    extensions: *ref_0
sendOperations:
  - *ref_1
receiveOperations:
  - *ref_2
sendMessages:
  - *ref_3
  - *ref_4
receiveMessages:
  - *ref_5
extensions:
  - id: x-parser-unique-object-id
    value: wallet-trades
securitySchemes: []

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.