# Offer Views

Mangrove exposes a range of getter functions to query offer lists and offers directly on-chain or via helper contracts.

#### Getting the Best Offer

```
uint best = mgv.best(olKey);
```

Returns the ID of the best available offer (highest bid or lowest ask, depending on the side).

Solidity

```solidity
import {IMangrove} from "@mgv/src/IMangrove.sol";
// context of the call

// IMangrove mgv = IMangrove(payable(<address of Mangrove>));
IMangrove mgv = IMangrove(payable(mgv));

// OLKey olkey = OLKey(<address of outbound token>, <address of inbound token>, <tick spacing>);
OLKey memory olkey = OLKey(address(base), address(quote), 1);

uint best = mgv.best(olkey);
```

**Getting Offer Data**

| Function                              | Description                                    |
| ------------------------------------- | ---------------------------------------------- |
| `offers(olKey, offerId)`              | Returns packed offer data                      |
| `offerDetails(olKey, offerId)`        | Returns packed offer detail data               |
| `offerData(olKey, offerId)`           | Returns both offer and detail in packed format |
| `MgvReader.offerInfo(olKey, offerId)` | Returns unpacked structs for off-chain use     |

> The data pertaining to a particular offer is contained in the `OfferUnpacked` and `OfferDetailUnpacked` structs, which are stored as packed custom types called, respectively, `OfferPacked` and `OfferDetailPacked`. For on-chain calls, Mangrove provides unpacking functions to extract a particular field out of a packed structure. For off-chain calls, Mangrove also provide direct getters for the unpacked structures.

Solidity

```solidity
import {IMangrove} from "@mgv/src/IMangrove.sol";
import {MgvReader} from "@mgv/src/periphery/MgvReader.sol";
import "@mgv/src/core/MgvLib.sol";

// context of the call

// IMangrove mgv = IMangrove(payable(<address of Mangrove>));
IMangrove mgv = IMangrove(payable(mangroveAddress));

// MgvReader reader = MgvReader(<address of MgvReader>);
MgvReader reader = MgvReader(readerAddress);

// OLKey olKey = OLKey(<address of outbound token>, <address of inbound token>, <tick spacing>);
OLKey memory olKey = OLKey(address(base), address(quote), 1);

// Tick tick = TickLib.tickFromVolumes(<inbound amount>, <outbound amount>);
// ratio = <inbound amount> / <outbound amount>
Tick tick = TickLib.tickFromVolumes(5, 4);  // ratio = 5/4 = 1.25

// creates an offer at `tick` and store its ID in ofrId
// newOfferByTick(<offer list key>, <tick>, <gives>, <gasreq>, <gasprice>)
uint ofrId = mgv.newOfferByTick(olKey, tick, 1 ether, 10_000, 20);

// getting packed offer data
Offer offer = mgv.offers(olKey, ofrId);
OfferDetail detail = mgv.offerDetails(olKey, ofrId);
(offer, detail) = mgv.offerData(olKey, ofrId);

// for all fields f of OfferUnpacked
// offer.f == offer32.f()
// for all fields f of OfferDetailUnpacked
// offerDetail.f == offerDetail32.f()

// getting unpacked offer data
// MgvReader.offerInfo(<offer list key>, <offer ID>);
(OfferUnpacked memory offer, OfferDetailUnpacked memory offerDetail) =
  reader.offerInfo(olKey, offerId);
```

#### **Checking Offer Liveness**

An offer is *live* if it can be matched by a taker (i.e., `gives > 0`).

```solidity
bool isLive = mgv.offers(olKey, offerId).isLive();
```

Solidity

```solidity
import {IMangrove} from "@mgv/src/IMangrove.sol";

// context of the call

// IMangrove mgv = IMangrove(payable(<address of Mangrove>));
IMangrove mgv = IMangrove(payable(mgv));

// OLKey olkey = OLKey(<address of outbound token>, <address of inbound token>, <tick spacing>);
OLKey memory olKey = OLKey(address(base), address(quote), 1);

// Tick tick = TickLib.tickFromVolumes(<inbound amount>, <outbound amount>);
// ratio = <inbound amount> / <outbound amount>
Tick tick = TickLib.tickFromVolumes(5, 4);  // ratio = 5/4 = 1.25

// creates an offer at `tick` and store its ID in ofrId
// newOfferByTick(<offer list key>, <tick>, <gives>, <gasreq>, <gasprice>)
uint ofrId = mgv.newOfferByTick(olKey, tick, 1 ether, 10_000, 20);

// checking whether the offer is live in the offer list
bool isLive = mgv.offers(olKey, ofrId).isLive();
```

#### Custom types

Offer data is split between `OfferUnpacked` and `OfferDetailUnpacked` for storage read/write optimization (as both structs can be efficiently packed in storage).

### `OfferUnpacked`

| Field   | Type   | Comments                                                            |
| ------- | ------ | ------------------------------------------------------------------- |
| `prev`  | `uint` | ID of the preceding offer with the same tick (if the offer is live) |
| `next`  | `uint` | ID of the next offer with the same tick (if the offer is live)      |
| `tick`  | `Tick` | The offer's "price" tick                                            |
| `gives` | `uint` | The amount of outbound token the offer gives                        |

### `OfferDetailUnpacked`

| Field                | Type      | Comments                                                                           |
| -------------------- | --------- | ---------------------------------------------------------------------------------- |
| `maker`              | `address` | Address of the offer maker, either an EOA or a Maker contract                      |
| `gasreq`             | `uint`    | Gas required by the offer (in gas units)                                           |
| `kilo_offer_gasbase` | `uint`    | Mangrove's `kilo_offer_gasbase` at the time the offer was posted (in 1k gas units) |
| `gasprice`           | `uint`    | The gas price covered by the offer bounty (in *Mwei* per gas unit)                 |
