# PartyB Open Facet

Where PartyA submits an intent expressing their desire to open an options position, PartyB uses this facet to act on it — locking it to signal intent to fill, filling it to actually open the trade, or handling cancellation requests from PartyA.

> **Key Concepts:**
>
> * **Lock:** Before filling an intent, PartyB must first lock it. Locking moves the intent from `PENDING` to `LOCKED` and prevents any other PartyB from acting on it during that window.
> * **Unlock:** If PartyB locks an intent but decides not to fill it (or can't), they release it back to `PENDING` so other PartyBs can pick it up. If the deadline has passed by the time they unlock, the intent transitions to `EXPIRED` instead.
> * **Partial Fill:** PartyB can fill less than the full requested quantity. When this happens, the library automatically creates a new residual open intent for the unfilled portion, so PartyA's remaining exposure stays in the market.
> * **Residual Intent:** The new intent created after a partial fill mirrors the original but with the remaining quantity. It immediately emits a `SendOpenIntent` event so other solvers can index it just like a fresh intent.
> * **CANCEL\_PENDING:** If PartyA requests cancellation while their intent is locked, it moves to `CANCEL_PENDING`. `acceptCancelOpenIntent()` is PartyB's acknowledgement, fully cancelling it.
> * **onlyPartyB:** The `lockOpenIntent()` function is restricted to registered PartyB addresses — only recognized market makers can lock intents.

***

#### Overview

The full PartyB open-side flow for a typical trade looks like this:

1. PartyA submits an open intent via `PartyAOpenFacet.sendOpenIntent()` — it sits `PENDING`
2. PartyB spots the intent and locks it via `lockOpenIntent()`, moving it to `LOCKED`
3. PartyB fills the intent via `fillOpenIntent()` at a price at least as favorable as PartyA's — a new `Trade` is created
4. If the fill is partial, a residual open intent is automatically created for the unfilled quantity
5. If PartyB locked the intent but can't fill it, they release it with `unlockOpenIntent()`
6. If PartyA requested cancellation while the intent was locked, PartyB processes it via `acceptCancelOpenIntent()`

***

### lockOpenIntent()

Reserves an open intent for PartyB to fill. Once locked, no other PartyB can act on the intent. This gives the locking PartyB an exclusive window to prepare and submit their fill.

**Function Signature:**

```solidity
function lockOpenIntent(uint256 intentId) external whenPartyNotPaused(msg.sender) onlyPartyB(msg.sender);
```

**Parameters:**

* **intentId:** The unique identifier of the open intent to lock. Must currently be in `PENDING` state.

***

### unlockOpenIntent()

Releases a previously locked intent back to an available state. Only the PartyB that locked it can unlock it. The resulting state depends on whether the intent's deadline has passed:

* If the deadline **has not passed** → intent returns to `PENDING`, available for any eligible PartyB to lock again
* If the deadline **has passed** → intent moves to `EXPIRED` instead

**Function Signature:**

```solidity
function unlockOpenIntent(uint256 intentId) external whenPartyNotPaused(msg.sender);
```

**Parameters:**

* **intentId:** The unique identifier of the locked open intent to release.

***

#### acceptCancelOpenIntent()

Accepts a pending cancellation request from PartyA. When PartyA calls `cancelOpenIntent()` while an intent is locked, it can't cancel immediately — instead it moves to `CANCEL_PENDING`. This function is how the locking PartyB acknowledges that and finalises the cancellation.

**Function Signature:**

```solidity
function acceptCancelOpenIntent(uint256 intentId) external whenPartyNotPaused(msg.sender);
```

**Parameters:**

* **intentId:** The unique identifier of the open intent in `CANCEL_PENDING` state.

***

### fillOpenIntent()

Opens a trade by filling a locked open intent. This is the core action — it creates a new `Trade` record between PartyA and PartyB at the agreed price. PartyB can fill the full requested quantity or a partial amount. If partial, a residual intent is automatically created for the remainder.

**Function Signature:**

```solidity
function fillOpenIntent(
    uint256 intentId,
    uint256 quantity,
    uint256 price
) external whenPartyNotPaused(msg.sender);
```

**Parameters:**

* **intentId:** The unique identifier of the locked open intent to fill.
* **quantity:** The amount to fill. Must be greater than zero and no more than the remaining unfilled quantity on the intent.
* **price:** The price at which PartyB is opening the trade. Must be at least as favorable to PartyA as the price they specified in the intent — the library enforces this check.
