Placing and canceling an order

Instructions for how to place an order via API endpoint.

Orders on Hook are placed via a mutation in our public GraphQL API. Once they have been validated, they are placed in a FIFO queue for matching. Once matched, the order is sent via our relayer to the Odyssey Protocol residing on Hook Chain.

The orderbook and account state can be subscribed to via WS to easily monitor the DEX state.

Populating the order payload

This payload must be completed to submit an order.

input PlaceOrderInput {
  marketHash: String!
  """
  The instrument hash of the instrument being traded.
  This hash may be retrieved by subscribing to the BBO subscription
  to see the current valid instruments in the market.
  """
  instrumentHash: String!
  """
  The string-encoded subaccount placing the order. This subaccount may not have
  a position in an instrument in another market.
  """
  subaccount: BigInt!
  """
  Market or Limit order. If order is MARKET, it should have a Time in Force of IOC.
  """
  orderType: OrderType!
  """
  BUY to long the instrument,  SHORT to sell the instrument.
  """
  direction: OrderDirection!
  """
  Number of contracts to buy/sell, using 1e18 decimals.
  """
  size: BigInt!
  """
  If a limit order, the price expressed in the market's BaseCurrency
  null if a market order.
  """
  limitPrice: BigInt
  volatilityBips: Int
  """
  GoodTilCanceled or GoodTilDate. If GoodTilDate, the expiration field must be set.
  """
  timeInForce: TimeInForce!
  """
  Expiration UNIX timestamp of the order.
  """
  expiration: DateTime
  """
  Cryptographic nonce for the order, user-specified.
  """
  nonce: BigInt!
  """
  If true, the order cannot be a taker when matched, even if it crossed
  another limit order when added to the orderbook.
  """
  postOnly: Boolean
  """
  If true, this order cannot increase the magnitude of the subaccount's position.
  """
  reduceOnly: Boolean
}

Signing the order signature

The fields above are encoded into an EIP712 signature. The signature should have the following typehash.

Order(bytes32 market,uint8 instrumentType,bytes32 instrumentId,uint8 direction,uint256 maker,uint256 taker,uint256 amount,uint256 limitPrice,uint256 expiration,uint256 nonce,uint256 counter,bool postOnly,bool reduceOnly,bool allOrNothing)

For the instrument type, 0 can be used for perps, 1 may be used for call options, 2 may be used for put options. For the direction, 0 can be used for BUY and 1 can be used for sell. Unless the user's counter has been incremented, 0 may be used to populate the counter.

Populating the taker field with non-zero values is currently unsupported.

Submitting the mutation

Submit the mutation via our API (Queries + Mutations).

placeOrderV2(
  beforeTradeTransfer: TransferInput
  beforeTradeTransferSignature: SignatureInput
  orderInput: PlaceOrderInput!
  signature: SignatureInput!
): Boolean!

The Signature should be populated by the signature from the previous step.

Monitoring the order/order error states

UsersUser's may subscribe to the SubaccountOrders subscription to monitor their orders.

 subaccountOrders(subaccount: BigInt!): SubaccountOrderEvent!   

Orders have the following statuses

enum OrderStatus {
  ### Order is unfilled (generally LIMIT)
  OPEN

  ### Order is partially matched, but the fill is still pending confirmation onchain
  PARTIALLY_MATCHED
  
  ### Order is fully matched, but the fill is not confirmed
  MATCHED
  
  ### Order is partially filled onchain
  PARTIALLY_FILLED
  
  ### Order is completely filled onchain
  FILLED
  
  ### Trader has canceled the order
  CANCELED
  
  ### Order is not fillable, due to insufficient liquidity or insufficient margin
  UNFILLABLE
  
  ### Order is expired and no longer fillable
  EXPIRED
  
  ### Order signature or size is immediately rejected
  REJECTED
}

For orders with a REJECTED order state the SubaccountOrder's errorReason field may populated with additional information.

Canceling orders

With a valid API key associated with the owner of a subaccount, a user may cancel orders in that subaccount using the following two mutations.

 """
  Soft/best-effort cancellation of an order. If the order is already submitted on chain, 
  it may be filled despite a cancel request. 
  """
  cancelOrder(
    subaccountID: BigInt!
    orderHash: String!
  ): Boolean!

  """
  Soft/best effort cancellation of all orders in the subaccount. If the order is already submitted on chain, 
  it may be filled despite a cancel request. 
  """
  cancelAllOrders(
    subaccountID: BigInt!
  ): Boolean!

Last updated