# Combos

> ComboPlayer and ComboMaker: request, quote and accept combinations.

Source: https://docs.stxapp.io/sdks/typescript/reference/combos/

The walkthrough is [Combos](/sdks/typescript/combos/).

## `ComboPlayer`

The player's side of combos, on `rfq:<user_id>`. Get one with
`ws.comboPlayer()`.

A request belongs to this channel: leaving or a dropped socket ends it
`cancelled`, and the SDK's automatic rejoin does not bring it back.
Every refusal throws `STXComboRefusedException` with the exchange's
`reason` in `code`.

### Properties

| Property | Type | Description |
|---|---|---|
| `channel` | `Channel` | The underlying channel. Its `reply` is the latest join reply. |
| `events` | `readonly E[]` | The events received so far (the latest 1000), oldest first. |
| `externalId` | `string` | Your account's pseudonym for counterparties, from the join reply. |

### Methods

#### `[asyncIterator]()`

```ts
[asyncIterator](): AsyncIterator<ComboPlayerEvent>
```

Returns `AsyncIterator<ComboPlayerEvent>`.

#### `accept()`

```ts
accept(rfqId: string, quoteId: string, amount: string): Promise<ComboPlacement>
```

`accept`: bind the request at `amount` or more, normally the amount
`best_quote` showed. The best live quote binds whoever made it, so the
placement can be better than `amount`. Waits up to 35 s.

Throws `STXComboPriceMovedException` (with the live `best`) when nothing
at least as good is live; the request stays open and you can accept again.
The reply says what was placed; fills arrive on `fills`.

| Parameter | Type | Description |
|---|---|---|
| `rfqId` | `string` | The request. |
| `quoteId` | `string` | The quote you saw, normally from `best_quote`. |
| `amount` | `string` | The least amount you take, e.g. `"1750.00"`. |

Returns `Promise<ComboPlacement>`.

#### `cancel()`

```ts
cancel(rfqId: string): Promise<ComboCancelReply>
```

`cancel`: end the request and drop every quote on it.

| Parameter | Type | Description |
|---|---|---|
| `rfqId` | `string` | The request. |

Returns `Promise<ComboCancelReply>`.

#### `cashOut()`

```ts
cashOut(marketId: string): Promise<ComboCashOutReply>
```

`cash_out`: ask makers to quote for what you hold of a combination, by the
`market_id` from `placed`. The exchange sets the size.

| Parameter | Type | Description |
|---|---|---|
| `marketId` | `string` | The combination's market id. |

Returns `Promise<ComboCashOutReply>`.

#### `leave()`

```ts
leave(): Promise<void>
```

Leave the topic. Requests opened and quotes placed on this channel end
(`cancelled`), as on any close, and delivery on this channel stops when
`leave()` resolves: the exchange's `negotiation_closed` for those requests
arrives after the channel has closed and is not passed to `onEvent` or to
an iterator. Treat every request still open here as cancelled once
`leave()` resolves. To see each request's own close first, `cancel()` it
and wait for its `negotiation_closed` before leaving. Other connections of
the same member still receive the close.

Returns `Promise<void>`.

#### `next()`

```ts
next(timeoutMs?: number | null): Promise<ComboPlayerEvent>
```

The next event, in arrival order. Rejects with `STXTimeoutException` when
none arrives within `timeoutMs`, and with `STXChannelException` once the
channel is closed. Use either this or `for await`, not both.

| Parameter | Type | Description |
|---|---|---|
| `timeoutMs` (optional) | `number \| null` |  |

Returns `Promise<ComboPlayerEvent>`.

#### `requestQuote()`

```ts
requestQuote(legs: readonly ComboLeg[], amount: string): Promise<ComboRequestReply>
```

`request_quote`: ask makers to quote on these legs for a stake. `amount`
is the stake as a decimal string in whole cents, e.g. `"250.00"`. Makers
quote what you win; quotes arrive as `best_quote` events.

| Parameter | Type | Description |
|---|---|---|
| `legs` | `readonly ComboLeg[]` | Two or more `open` markets and the outcome the combination needs of each. |
| `amount` | `string` | The stake in dollars, e.g. `"250.00"`. |

Returns `Promise<ComboRequestReply>`.

#### `snapshot()`

```ts
snapshot(rfqId: string): Promise<ComboSnapshot>
```

`snapshot`: the request now, with the live best quote. Not delayed like `best_quote` events.

| Parameter | Type | Description |
|---|---|---|
| `rfqId` | `string` | The request. |

Returns `Promise<ComboSnapshot>`.

#### `waitFor()`

```ts
waitFor(event: K | readonly K[], opts?: { quoteId?: string; rfqId?: string; timeoutMs?: number }): Promise<Extract<{ event: "best_quote"; payload: ComboBestQuoteEvent }, { event: K }> | Extract<{ event: "placed"; payload: ComboPlacedEvent }, { event: K }> | Extract<{ event: "negotiation_closed"; payload: ComboRequestClosedEvent }, { event: K }>>
```

Resolve with the first event named `event` (or one of several) for
`rfqId`, looking first at events already received. Unlike `next()`, it
takes nothing from the queue. Rejects with `STXTimeoutException` after
`timeoutMs` (default 10000).

| Parameter | Type | Description |
|---|---|---|
| `event` | `K \| readonly K[]` | An event name, or several. |
| `opts` (optional) | `{ quoteId?: string; rfqId?: string; timeoutMs?: number }` |  |
| `opts.quoteId` (optional) | `string` | Only events for this quote (maker events). |
| `opts.rfqId` (optional) | `string` | Only events for this request. |
| `opts.timeoutMs` (optional) | `number` | Milliseconds to wait. Default 10000. |

Returns `Promise<Extract<{ event: "best_quote"; payload: ComboBestQuoteEvent }, { event: K }> \| Extract<{ event: "placed"; payload: ComboPlacedEvent }, { event: K }> \| Extract<{ event: "negotiation_closed"; payload: ComboRequestClosedEvent }, { event: K }>>`.

## `ComboMaker`

The maker's side of combos, on `combo_quote:<user_id>`. Get one with
`ws.comboMaker()`. Joining subscribes to every request opened after the
join (`rfq_opened`); earlier requests are not replayed.

A quote belongs to this channel: leaving or a dropped socket withdraws it.
Every refusal throws `STXComboRefusedException` with the exchange's
`reason` in `code`.

### Properties

| Property | Type | Description |
|---|---|---|
| `channel` | `Channel` | The underlying channel. Its `reply` is the latest join reply. |
| `events` | `readonly E[]` | The events received so far (the latest 1000), oldest first. |
| `externalId` | `string` | Your account's pseudonym for counterparties, from the join reply. |

### Methods

#### `[asyncIterator]()`

```ts
[asyncIterator](): AsyncIterator<ComboMakerEvent>
```

Returns `AsyncIterator<ComboMakerEvent>`.

#### `leave()`

```ts
leave(): Promise<void>
```

Leave the topic. Requests opened and quotes placed on this channel end
(`cancelled`), as on any close, and delivery on this channel stops when
`leave()` resolves: the exchange's `negotiation_closed` for those requests
arrives after the channel has closed and is not passed to `onEvent` or to
an iterator. Treat every request still open here as cancelled once
`leave()` resolves. To see each request's own close first, `cancel()` it
and wait for its `negotiation_closed` before leaving. Other connections of
the same member still receive the close.

Returns `Promise<void>`.

#### `next()`

```ts
next(timeoutMs?: number | null): Promise<ComboMakerEvent>
```

The next event, in arrival order. Rejects with `STXTimeoutException` when
none arrives within `timeoutMs`, and with `STXChannelException` once the
channel is closed. Use either this or `for await`, not both.

| Parameter | Type | Description |
|---|---|---|
| `timeoutMs` (optional) | `number \| null` |  |

Returns `Promise<ComboMakerEvent>`.

#### `quote()`

```ts
quote(rfqId: string, amount: string, expiresInMs: number, opts?: { clientOrderId?: string | null }): Promise<ComboQuoteReply>
```

`quote`: offer `amount` on a request. On a buy it is what the player wins;
on a cash out, what you pay for the whole size. Price it against the
request's `max_price` and `tick_size`. `expiresInMs` (a positive integer)
counts from receipt; the quote ends no later than its request.
`clientOrderId` (at most 255 bytes) is copied onto your order if it binds.

| Parameter | Type | Description |
|---|---|---|
| `rfqId` | `string` | The request, from `rfq_opened`. |
| `amount` | `string` | In dollars, e.g. `"1750.00"`. |
| `expiresInMs` | `number` | How long the quote stands, in milliseconds. |
| `opts` (optional) | `{ clientOrderId?: string \| null }` |  |
| `opts.clientOrderId` (optional) | `string \| null` | Copied onto your order if the quote binds. |

Returns `Promise<ComboQuoteReply>`.

#### `waitFor()`

```ts
waitFor(event: K | readonly K[], opts?: { quoteId?: string; rfqId?: string; timeoutMs?: number }): Promise<Extract<{ event: "rfq_opened"; payload: ComboRfqOpenedEvent }, { event: K }> | Extract<{ event: "rfq_closed"; payload: ComboRfqClosedEvent }, { event: K }> | Extract<{ event: "quote_accepted"; payload: ComboQuoteAcceptedEvent }, { event: K }> | Extract<{ event: "placed"; payload: ComboMakerPlacedEvent }, { event: K }> | Extract<{ event: "negotiation_closed"; payload: ComboQuoteClosedEvent }, { event: K }>>
```

Resolve with the first event named `event` (or one of several) for
`rfqId`, looking first at events already received. Unlike `next()`, it
takes nothing from the queue. Rejects with `STXTimeoutException` after
`timeoutMs` (default 10000).

| Parameter | Type | Description |
|---|---|---|
| `event` | `K \| readonly K[]` | An event name, or several. |
| `opts` (optional) | `{ quoteId?: string; rfqId?: string; timeoutMs?: number }` |  |
| `opts.quoteId` (optional) | `string` | Only events for this quote (maker events). |
| `opts.rfqId` (optional) | `string` | Only events for this request. |
| `opts.timeoutMs` (optional) | `number` | Milliseconds to wait. Default 10000. |

Returns `Promise<Extract<{ event: "rfq_opened"; payload: ComboRfqOpenedEvent }, { event: K }> \| Extract<{ event: "rfq_closed"; payload: ComboRfqClosedEvent }, { event: K }> \| Extract<{ event: "quote_accepted"; payload: ComboQuoteAcceptedEvent }, { event: K }> \| Extract<{ event: "placed"; payload: ComboMakerPlacedEvent }, { event: K }> \| Extract<{ event: "negotiation_closed"; payload: ComboQuoteClosedEvent }, { event: K }>>`.

#### `withdrawQuote()`

```ts
withdrawQuote(rfqId: string, quoteId: string): Promise<ComboWithdrawReply>
```

`withdraw_quote`: remove one of your quotes.

| Parameter | Type | Description |
|---|---|---|
| `rfqId` | `string` | The request. |
| `quoteId` | `string` | Your quote, from the `quote()` reply. |

Returns `Promise<ComboWithdrawReply>`.
