# Place Limit Order

## Overview

Limit orders provide the primary mechanism for trading on Duality. Limit orders can provide liquidity to the Dex (“Maker LimitOrders”) and/or can be used to trade against preexisting liquidity (“Taker Limit Orders”). All limit orders provide a `TickIndex`which serves as a limit price for which the order will be executed at.

Maker limit orders provide new liquidity to the dex that can be swapped through by other traders (either via Multihop Swap or a Taker Limit Order.) The liquidity supplied by a maker limit order is stored in a `LimitOrderTranche` at a specific tick. Once the tranche has been fully or partially filled via another order the user can withdraw the proceeds from that tranche. Maker limit orders can also be cancelled at any time. Maker only limit order’s are created with the following order types: GOOD\_TIL\_CANCELLED (will first try to satisfy the order via a taker limit order and only create an maker order if there is insufficient liquidity available above the provided `TickIndex`) JUST\_IN\_TIME GOOD\_TIL\_TIME

Taker limit orders do not add liquidity to the dex, instead they trade against existing `TickLiquidity`. Taker orders will either fail at the time of transaction or be completed immediately. Successful taker orders will deposit the proceeds directly back into the receiever’s address.

Rather than supplying a limit price, limit orders take a `TickIndex` as an argument. For maker limit orders this is the tick that the `LimitOrderTranche` will be placed at. For taker limit order will only trade through liquidity at or above the `TickIndex.` A specific price can be converted to a `TickIndex` using the following formula:

$$TickIndex = log\_{1.0001}(price)$$

## Order types

### FILL\_OR\_KILL

Fill-or-Kill limit orders are maker limit orders that either successfully swap 100% of the supplied `AmountIn` or return an error. If there is insufficient liquidity to complete the trade at or above the supplied `TickIndex` a Fill-or-Kill order will return an error of `ErrFoKLimitOrderNotFilled.`

### IMMEDIATE\_OR\_CANCEL

Immediate-or-Cancel limit orders are maker orders that will swap as much as of the `AmountIn` as possible given available liquidity above the supplied `TickIndex`. Unlike Fill-or-Kill orders they will still successfully complete even if they are only able to partially trade through the `AmountIn` at the `TickIndex` or better.

### GOOD\_TIL\_CANCELLED

Good-til-Cancelled limit orders are hybrid maker and taker limit orders. They will attempt to trade the supplied `AmountIn` at the `TickIndex` or better. However, if the total `AmountIn` cannot be traded at the limit price they remaining amount will be placed as a maker limit order. The proceeds from the taker portion are deposited into the user’s account immediately, however, the proceeds from the maker portion must be explicitly withdrawn via WithdrawLimitOrder.

### GOOD\_TIL\_TIME

Good-til-Time limit order function exactly the same as Good-til-Cancelled limit orders first trying to trade as a taker limit order and then placing any remaining amount as a maker limit order. However, the maker portion of the limit order has a specified `ExpirationTime`. After the `ExpirationTime` the order will be cancelled and can no longer be traded against. When withdrawing a Good-til-Time limit order the user will receive both the successfully traded portion of the limit order (TokenOut) as well as any remaining untraded amount (TokenIn).

### JUST\_IN\_TIME

Just-in-Time limit orders are an advanced maker limit order order that provides tradeable liquidity for exactly one block. At the end of the same block in which the Just-in-Time order was submitted the order is canceled and any untraded portion will no longer be usable as active liquidity.

## PlaceLimitOrder Message

```protobuf
message MsgPlaceLimitOrder {
    string creator = 1;
    string receiver = 2;
    string token_in = 3;
    string token_out = 4;
    int64 tick_index_in_to_out = 5;
    string amount_in = 7 [
        (gogoproto.moretags) = "yaml:\"amount_in\"",
        (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
        (gogoproto.nullable) = false,
        (gogoproto.jsontag) = "amount_in"
    ];
    LimitOrderType order_type = 8;
    // expirationTime is only valid iff orderType == GOOD_TIL_TIME.
    google.protobuf.Timestamp expiration_time = 9 [
        (gogoproto.stdtime) = true,
        (gogoproto.nullable) = true
    ];
    string max_amount_out = 10 [
        (gogoproto.moretags) = "yaml:\"max_amount_out\"",
        (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int",
        (gogoproto.nullable) = true,
        (gogoproto.jsontag) = "max_amount_out"
    ];
}
```

### MsgPlaceLimitOrder

| Field                              | Desciption                                                                                                                                      |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `Creator` string (sdk.AccAddress)  | Account from which TokenIn is debited                                                                                                           |
| `Receiver` string (sdk.AccAddress) | Account to which TokenOut is credited or that will be allowed to withdraw or cancel a maker order                                               |
| `TokenIn` string                   | Token being “sold”                                                                                                                              |
| `TokenOut`                         | Token being “bought”                                                                                                                            |
| `TickIndex` int64                  | Limit tick for a limit order, specified in terms of TokenIn to TokenOut                                                                         |
| `AmountIn` sdk.Int                 | Amount of TokenIn to be traded                                                                                                                  |
| `OrderType` orderType              | Type of limit order to be used. Must be one of: GOOD\_TIL\_CANCELLED, FILL\_OR\_KILL, IMMEDIATE\_OR\_CANCEL, JUST\_IN\_TIME, or GOOD\_TIL\_TIME |
| `ExpirationTime` time.Time         | Expiration time for order. Only valid for GOOD\_TIL\_TIME limit orders                                                                          |
