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

# Client Messages

> Complete schema and JSON examples for all 9 client message types sent to the Exit Intelligence Stream.

## Message Types

| Type                       | Description                                      |
| -------------------------- | ------------------------------------------------ |
| `ping`                     | Latency probe; server responds with `pong`.      |
| `configure`                | Initial session setup with wallets and strategy. |
| `update_strategy`          | Change strategy parameters mid session.          |
| `close_position`           | Remove a position from tracking.                 |
| `request_exit_signal`      | Manually request an exit transaction.            |
| `update_wallets`           | Add or remove wallets mid session.               |
| `update_position_strategy` | Override strategy for a single position.         |
| `update_watch_wallets`     | Add or update watch wallets for copy trading.    |
| `mirror_buy_result`        | Report outcome of a mirror buy transaction.      |

## `ping`

```json theme={null}
{
  "type": "ping",
  "client_time_ms": 1706000000000
}
```

| Field            | Type     | Required | Description                                                                              |
| ---------------- | -------- | -------- | ---------------------------------------------------------------------------------------- |
| `client_time_ms` | `number` | Yes      | Client timestamp in milliseconds. Compare with `pong.server_time_ms` to measure latency. |

## `configure`

Sent once after receiving `hello_ok`. Sets the wallets to watch and the strategy to evaluate.

```json theme={null}
{
  "type": "configure",
  "wallet_pubkeys": [
    "WalletPubkey1...",
    "WalletPubkey2..."
  ],
  "strategy": {
    "target_profit_pct": 5.0,
    "stop_loss_pct": 1.5,
    "trailing_stop_pct": 3.0,
    "sell_on_graduation": false
  },
  "deadline_timeout_sec": 45,
  "send_mode": "helius_sender",
  "tip_lamports": 1000,
  "watch_wallets": [
    { "pubkey": "WatchWalletPubkey1..." },
    { "pubkey": "WatchWalletPubkey2...", "auto_buy": { "wallet_pubkey": "YourBuyWallet...", "amount_quote_units": 100000000 } }
  ],
  "mirror_config": {
    "max_positions_per_wallet": 1,
    "cooldown_sec": 30,
    "skip_creator_tokens": false,
    "max_active_sol": 5.0,
    "buy_slippage_bps": 2500,
    "min_liquidity_sol": null,
    "max_entry_drift_pct": null,
    "max_consecutive_losses": null
  }
}
```

| Field                  | Type                    | Required | Description                                                                                                                                |
| ---------------------- | ----------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `wallet_pubkeys`       | `string[]`              | Yes      | One or more wallet public keys to monitor.                                                                                                 |
| `strategy`             | `object`                | Yes      | Strategy configuration. See [Strategy Configuration](/api/stream/strategy-configuration).                                                  |
| `deadline_timeout_sec` | `number`                | No       | Seconds of inactivity before the server auto-generates an exit signal. Omit or set to `0` to disable.                                      |
| `send_mode`            | `string`                | No       | Transaction submission mode: `"rpc"`, `"helius_sender"`, or `"astralane"`. Default: `"rpc"`.                                               |
| `tip_lamports`         | `number`                | No       | Priority fee tip in lamports. Default: `1000` (0.001 SOL).                                                                                 |
| `watch_wallets`        | `WatchWalletEntryMsg[]` | No       | Optional list of external wallets to mirror for copy trading. Each entry has `pubkey` (string) and optional `auto_buy` (AutoBuyConfigMsg). |
| `mirror_config`        | `MirrorConfigMsg`       | No       | Optional hardening settings for mirror trading. See [Mirror Config](#mirror-config) below.                                                 |

### Mirror Config

The `mirror_config` object controls safety limits and behavior for mirror (copy) trading. All fields are optional; the server uses sensible defaults when omitted.

| Field                      | Type      | Default | Description                                                                                                                                                        |
| -------------------------- | --------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `max_positions_per_wallet` | `number`  | `1`     | Maximum concurrent mirrored positions per watched wallet. Additional signals are ignored until an existing position closes.                                        |
| `cooldown_sec`             | `number`  | `30`    | Minimum seconds between mirror buys from the same watched wallet.                                                                                                  |
| `skip_creator_tokens`      | `boolean` | `false` | When `true`, ignore buy signals where the watched wallet is the token creator.                                                                                     |
| `max_active_sol`           | `number`  | `5.0`   | Maximum total SOL exposure across all active mirrored positions. New signals are skipped when this cap would be exceeded.                                          |
| `buy_slippage_bps`         | `number`  | `2500`  | Slippage tolerance in basis points for mirror buy transactions (2500 = 25%).                                                                                       |
| `min_liquidity_sol`        | `number`  | `null`  | Minimum pool liquidity in SOL required to execute a mirror buy. `null` to disable.                                                                                 |
| `max_entry_drift_pct`      | `number`  | `null`  | Maximum allowed price drift (%) from the watched wallet's entry price. `null` to disable.                                                                          |
| `max_consecutive_losses`   | `number`  | `null`  | After this many consecutive losing trades from a watched wallet, the wallet is auto-disabled and a `mirror_wallet_auto_disabled` event is sent. `null` to disable. |

The SDKs send `configure` automatically when you call `StreamClient.connect()` or `StreamSession.connect()`.

<Note>
  All wallets in `wallet_pubkeys` must be [registered](/api/exit-api/wallets) to your account before connecting. The stream will reject unregistered wallets with error code `wallet_not_registered`.
</Note>

## `update_strategy`

Update the strategy without reconnecting. Takes effect immediately for all tracked positions.

```json theme={null}
{
  "type": "update_strategy",
  "strategy": {
    "target_profit_pct": 15.0,
    "stop_loss_pct": 3.0,
    "trailing_stop_pct": 7.0,
    "sell_on_graduation": true
  }
}
```

| Field      | Type     | Required | Description            |
| ---------- | -------- | -------- | ---------------------- |
| `strategy` | `object` | Yes      | New strategy to apply. |

<CodeGroup>
  ```typescript TypeScript theme={null}
  session.updateStrategy({
    target_profit_pct: 15,
    stop_loss_pct: 3,
    trailing_stop_pct: 7,
  });
  ```

  ```python Python theme={null}
  session.sender().update_strategy({
      "target_profit_pct": 15.0,
      "stop_loss_pct": 3.0,
      "trailing_stop_pct": 7.0,
  })
  ```

  ```rust Rust theme={null}
  session.update_strategy(StrategyConfigMsg {
      target_profit_pct: 15.0,
      stop_loss_pct: 3.0,
      trailing_stop_pct: Some(7.0),
      sell_on_graduation: None,
  }, None);
  ```

  ```go Go theme={null}
  session.Sender().UpdateStrategy(stream.StrategyConfigMsg{
      TargetProfitPct: 15.0,
      StopLossPct:     3.0,
      TrailingStopPct: 7.0,
  })
  ```
</CodeGroup>

## `close_position`

Remove a position from tracking. The server will stop monitoring PnL and will not generate exit signals for it. Identify the position by either `position_id` or `token_account`.

```json theme={null}
{
  "type": "close_position",
  "position_id": 1
}
```

Or by token account:

```json theme={null}
{
  "type": "close_position",
  "token_account": "ATA..."
}
```

| Field           | Type     | Required | Description                                                    |
| --------------- | -------- | -------- | -------------------------------------------------------------- |
| `position_id`   | `number` | No\*     | Position ID to close. Mutually exclusive with `token_account`. |
| `token_account` | `string` | No\*     | Token account address. Mutually exclusive with `position_id`.  |

\*One of `position_id` or `token_account` is required.

<CodeGroup>
  ```typescript TypeScript theme={null}
  // By handle (from StreamSession)
  session.close(handle);

  // By position ID (via sender)
  session.sender().closeById(1);

  // By token account
  session.sender().closePosition("ATA...");
  ```

  ```python Python theme={null}
  # By position ID
  session.sender().close_by_id(1)

  # By token account
  session.sender().close_position("ATA...")
  ```

  ```rust Rust theme={null}
  // By position handle
  session.close(handle);

  // By position ID
  session.sender().close_by_id(1);

  // By token account
  session.sender().close_position("ATA...");
  ```

  ```go Go theme={null}
  // By position ID
  sender.CloseByID(1)

  // By token account
  sender.ClosePosition("ATA...")
  ```
</CodeGroup>

## `request_exit_signal`

Manually request the server to generate an exit transaction for a position, regardless of whether the strategy thresholds have been met.

```json theme={null}
{
  "type": "request_exit_signal",
  "position_id": 1,
  "slippage_bps": 3000
}
```

Or by token account:

```json theme={null}
{
  "type": "request_exit_signal",
  "token_account": "ATA...",
  "slippage_bps": 3000
}
```

| Field           | Type     | Required | Description                                           |
| --------------- | -------- | -------- | ----------------------------------------------------- |
| `position_id`   | `number` | No\*     | Position ID. Mutually exclusive with `token_account`. |
| `token_account` | `string` | No\*     | Token account. Mutually exclusive with `position_id`. |
| `slippage_bps`  | `number` | No       | Override slippage for this exit transaction.          |

\*One of `position_id` or `token_account` is required.

The server responds with an `exit_signal_with_tx` containing the unsigned transaction.

<CodeGroup>
  ```typescript TypeScript theme={null}
  // Using StreamSession
  session.requestExitSignal(handle, 3000);

  // Using sender directly
  session.sender().requestExitSignal("ATA...", 3000);
  session.sender().requestExitSignalById(1, 3000);
  ```

  ```python Python theme={null}
  session.sender().request_exit_signal("ATA...", slippage_bps=3000)
  session.sender().request_exit_signal_by_id(1, slippage_bps=3000)
  ```

  ```rust Rust theme={null}
  session.request_exit_signal(handle, Some(3000));

  // Using sender directly
  session.sender().request_exit_signal("ATA...", Some(3000));
  session.sender().request_exit_signal_by_id(1, Some(3000));
  ```

  ```go Go theme={null}
  sender.RequestExitSignal("ATA...", intPtr(3000))
  sender.RequestExitSignalByID(1, intPtr(3000))
  ```
</CodeGroup>

## `update_wallets`

Add or remove wallets from the session without reconnecting. The server will start monitoring the new set and stop tracking wallets that are no longer listed.

```json theme={null}
{
  "type": "update_wallets",
  "wallet_pubkeys": [
    "WalletPubkey1...",
    "WalletPubkey3..."
  ]
}
```

| Field            | Type       | Required | Description                         |
| ---------------- | ---------- | -------- | ----------------------------------- |
| `wallet_pubkeys` | `string[]` | Yes      | Updated list of wallets to monitor. |

<CodeGroup>
  ```typescript TypeScript theme={null}
  session.sender().updateWallets([
    "WalletPubkey1...",
    "WalletPubkey3...",
  ]);
  ```

  ```python Python theme={null}
  session.sender().update_wallets([
      "WalletPubkey1...",
      "WalletPubkey3...",
  ])
  ```

  ```rust Rust theme={null}
  session.sender().update_wallets(vec![
      "WalletPubkey1...".into(),
      "WalletPubkey3...".into(),
  ]);
  ```

  ```go Go theme={null}
  sender.UpdateWallets([]string{
      "WalletPubkey1...",
      "WalletPubkey3...",
  })
  ```
</CodeGroup>

## `update_position_strategy`

Override the strategy for a single position without affecting other tracked positions.

```json theme={null}
{
  "type": "update_position_strategy",
  "position_id": 1,
  "strategy": {
    "target_profit_pct": 200.0,
    "stop_loss_pct": 5.0,
    "trailing_stop_pct": 10.0
  }
}
```

| Field         | Type     | Required | Description                               |
| ------------- | -------- | -------- | ----------------------------------------- |
| `position_id` | `number` | Yes      | Position to override.                     |
| `strategy`    | `object` | Yes      | Strategy override for this position only. |

<CodeGroup>
  ```typescript TypeScript theme={null}
  session.sender().updatePositionStrategy(positionId, {
    target_profit_pct: 200,
    stop_loss_pct: 5,
    trailing_stop_pct: 10,
  });
  ```

  ```python Python theme={null}
  session.sender().update_position_strategy(position_id, {
      "target_profit_pct": 200.0,
      "stop_loss_pct": 5.0,
      "trailing_stop_pct": 10.0,
  })
  ```

  ```rust Rust theme={null}
  session.sender().update_position_strategy(position_id, StrategyConfigMsg {
      target_profit_pct: 200.0,
      stop_loss_pct: 5.0,
      trailing_stop_pct: 10.0,
      ..Default::default()
  })?;
  ```

  ```go Go theme={null}
  sender.UpdatePositionStrategy(positionID, stream.StrategyConfigMsg{
      TargetProfitPct: 200.0,
      StopLossPct:     5.0,
      TrailingStopPct: 10.0,
  })
  ```
</CodeGroup>

## `update_watch_wallets`

Add or update watch wallets mid-session for copy trading. Replaces the current watch wallet list.

```json theme={null}
{
  "type": "update_watch_wallets",
  "watch_wallets": [
    { "pubkey": "WatchWalletPubkey1..." },
    { "pubkey": "WatchWalletPubkey2...", "auto_buy": { "wallet_pubkey": "YourBuyWallet...", "amount_quote_units": 100000000 } }
  ]
}
```

| Field           | Type                    | Required | Description                        |
| --------------- | ----------------------- | -------- | ---------------------------------- |
| `watch_wallets` | `WatchWalletEntryMsg[]` | Yes      | Updated list of wallets to mirror. |

Each `WatchWalletEntryMsg` has:

| Field         | Type               | Required | Description                                                                                                                  |
| ------------- | ------------------ | -------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `pubkey`      | `string`           | Yes      | Public key of the wallet to watch.                                                                                           |
| `auto_buy`    | `AutoBuyConfigMsg` | No       | If set, automatically mirror buys from this wallet.                                                                          |
| `mirror_sell` | `boolean`          | No       | Reserved for future use. When `true`, mirror sells from this wallet in addition to buys. Default: `false`. Currently unused. |

`AutoBuyConfigMsg`:

| Field                | Type     | Required | Description                                 |
| -------------------- | -------- | -------- | ------------------------------------------- |
| `wallet_pubkey`      | `string` | Yes      | Your wallet that will execute the buy.      |
| `amount_quote_units` | `number` | Yes      | Amount in quote asset atomic units per buy. |
| `amount_usd1_units`  | `number` | No       | Amount in USD1 atomic units (alternative).  |

<CodeGroup>
  ```typescript TypeScript theme={null}
  session.sender().updateWatchWallets([
    { pubkey: "WatchWalletPubkey1..." },
    { pubkey: "WatchWalletPubkey2...", auto_buy: { wallet_pubkey: "YourBuyWallet...", amount_quote_units: 100000000 } },
  ]);
  ```

  ```python Python theme={null}
  session.sender().update_watch_wallets([
      {"pubkey": "WatchWalletPubkey1..."},
      {"pubkey": "WatchWalletPubkey2...", "auto_buy": {"wallet_pubkey": "YourBuyWallet...", "amount_quote_units": 100000000}},
  ])
  ```

  ```rust Rust theme={null}
  session.sender().update_watch_wallets(vec![
      WatchWalletEntryMsg { pubkey: "WatchWalletPubkey1...".into(), auto_buy: None },
      WatchWalletEntryMsg {
          pubkey: "WatchWalletPubkey2...".into(),
          auto_buy: Some(AutoBuyConfigMsg {
              wallet_pubkey: "YourBuyWallet...".into(),
              amount_quote_units: 100000000,
              amount_usd1_units: None,
          }),
      },
  ])?;
  ```

  ```go Go theme={null}
  sender.UpdateWatchWallets([]stream.WatchWalletEntryMsg{
      {Pubkey: "WatchWalletPubkey1..."},
      {Pubkey: "WatchWalletPubkey2...", AutoBuy: &stream.AutoBuyConfigMsg{
          WalletPubkey: "YourBuyWallet...", AmountQuoteUnits: 100000000,
      }},
  })
  ```
</CodeGroup>

## `mirror_buy_result`

Reports the outcome of a mirror buy transaction back to the stream. Send this after you sign and submit (or fail to submit) the transaction from a `mirror_buy_signal` event. The stream uses this feedback to update internal state, track consecutive losses, and manage cooldown timers.

```json theme={null}
{
  "type": "mirror_buy_result",
  "mint": "TokenMint...",
  "success": true
}
```

| Field     | Type      | Required | Description                                                                         |
| --------- | --------- | -------- | ----------------------------------------------------------------------------------- |
| `mint`    | `string`  | Yes      | Token mint address from the original `mirror_buy_signal`.                           |
| `success` | `boolean` | Yes      | `true` if the transaction was signed and submitted successfully, `false` otherwise. |

<CodeGroup>
  ```typescript TypeScript theme={null}
  session.sender().mirrorBuyResult("TokenMint...", true);
  ```

  ```python Python theme={null}
  session.sender().mirror_buy_result("TokenMint...", True)
  ```

  ```rust Rust theme={null}
  session.sender().mirror_buy_result("TokenMint...", true);
  ```

  ```go Go theme={null}
  sender.MirrorBuyResult("TokenMint...", true)
  ```
</CodeGroup>
