# Market Orders

Open a position at the current oracle price.

## `openMarketTradeV2`

```solidity
function openMarketTradeV2(
    OpenDataInput memory data,
    OracleUpdateData calldata updateData,
    uint96 extraFee
) external payable returns (bytes32 tradeHash);
```

Returns the **pending trade hash**, not the position hash. The position hash is deterministic and
separate — see [Positions are merged slots](/introduction/concepts#positions-are-merged-slots).

### `OpenDataInput`

```solidity
struct OpenDataInput {
    address pairBase;   // market identifier
    bool isLong;
    address tokenIn;    // collateral you deposit
    address lvToken;    // settlement token, see below
    uint96 amountIn;    // tokenIn decimals
    uint128 qty;        // base asset amount, 1e10
    uint128 price;      // worst acceptable price, 1e18
    uint128 stopLoss;   // 1e18, 0 to disable
    uint128 takeProfit; // 1e18, 0 to disable
    uint24 broker;      // referral id, 0 for the default broker
}
```

| Field | Notes |
| :--- | :--- |
| `pairBase` | From [`GET /v1/pairs`](/api/pairs#list-pairs). Do not hardcode. |
| `tokenIn` / `lvToken` | Must be a valid pair — [see the table](/introduction/concepts#collateral-and-lvtoken). |
| `amountIn` | Margin **plus** the open fee. Under-funding reverts. |
| `qty` | Base asset, 1e10. `$100 of BTC at $100k` → `10000000`. |
| `price` | Slippage bound, **not** a limit price. Long: maximum acceptable. Short: minimum acceptable. |
| `stopLoss` / `takeProfit` | Optional, set at open. Can be changed later, or replaced by [TP/SL orders](/onchain/tpsl-orders). |
| `broker` | Referral channel for this trade's fee. `0` credits the default broker, not "no broker" — see [Brokers & Referrals](/introduction/brokers). |

### `updateData` and `extraFee`

`updateData` is the oracle payload from
[`POST /v1/oracle/price/updates/by-position`](/api/oracle#price-updates-by-position). Attach
`updateFee + verifition_fee` as the transaction `value`.

`extraFee` is an optional surcharge you add on top of the trade, denominated in `tokenIn` and paid to
your broker's receiver when the position fills. Pass `0` unless you operate a broker integration.

When non-zero:

- It is transferred from the trader **in addition to** `amountIn`, so the allowance must cover
  `amountIn + extraFee`.
- It goes to the receiver of whatever `broker` id you passed — pairing `extraFee > 0` with
  `broker: 0` pays the default broker, not you.
- It is returned along with the collateral if the open is refunded.

See [Brokers & Referrals](/introduction/brokers#extrafee).

## Example

```ts
import { parseUnits } from 'viem'
import { publicClient, walletClient, account, DIAMOND, USDC, LVUSD } from './config'
import { fetchOracleUpdate } from './oracle'

const OPEN_MARKET_ABI = [{
  type: 'function',
  name: 'openMarketTradeV2',
  stateMutability: 'payable',
  inputs: [
    {
      name: 'data', type: 'tuple', components: [
        { name: 'pairBase', type: 'address' },
        { name: 'isLong', type: 'bool' },
        { name: 'tokenIn', type: 'address' },
        { name: 'lvToken', type: 'address' },
        { name: 'amountIn', type: 'uint96' },
        { name: 'qty', type: 'uint128' },
        { name: 'price', type: 'uint128' },
        { name: 'stopLoss', type: 'uint128' },
        { name: 'takeProfit', type: 'uint128' },
        { name: 'broker', type: 'uint24' },
      ],
    },
    {
      name: 'updateData', type: 'tuple', components: [
        { name: 'pythPriceUpdateData', type: 'bytes[]' },
        { name: 'pythProPriceUpdateData', type: 'bytes[]' },
      ],
    },
    { name: 'extraFee', type: 'uint96' },
  ],
  outputs: [{ name: 'tradeHash', type: 'bytes32' }],
}] as const

export async function openLong(
  pairBase: `0x${string}`,
  notionalUsd: number,
  marginUsdc: string,
  markPrice: number,
  slippagePct = 1,
) {
  const oracle = await fetchOracleUpdate(pairBase, USDC)

  const qty = parseUnits((notionalUsd / markPrice).toFixed(10), 10)
  const worstPrice = parseUnits(
    (markPrice * (1 + slippagePct / 100)).toFixed(18),
    18,
  )

  const hash = await walletClient.writeContract({
    address: DIAMOND,
    abi: OPEN_MARKET_ABI,
    functionName: 'openMarketTradeV2',
    args: [
      {
        pairBase,
        isLong: true,
        tokenIn: USDC,
        lvToken: LVUSD,
        amountIn: parseUnits(marginUsdc, 6),
        qty,
        price: worstPrice,
        stopLoss: 0n,
        takeProfit: 0n,
        broker: 0,
      },
      oracle.updateData,
      0n,
    ],
    value: oracle.value,
  })

  return publicClient.waitForTransactionReceipt({ hash })
}
```

For a short, set `isLong: false` and invert the slippage bound:

```ts
const worstPrice = parseUnits((markPrice * (1 - slippagePct / 100)).toFixed(18), 18)
```

## Using native MON as collateral

```ts
const oracle = await fetchOracleUpdate(pairBase, WMON)   // quote against WMON
const amountIn = parseUnits('1', 18)

await walletClient.writeContract({
  address: DIAMOND,
  abi: OPEN_MARKET_ABI,
  functionName: 'openMarketTradeV2',
  args: [
    { /* ... */ tokenIn: '0x0000000000000000000000000000000000000000', lvToken: LVMON, amountIn, /* ... */ },
    oracle.updateData,
    0n,
  ],
  value: amountIn + oracle.value,   // collateral travels as msg.value
})
```

No approval is needed for native MON.

## After sending

The transaction emits `MarketPendingTrade` and locks your collateral. A keeper then fills it:

- **Filled** → `OpenPosition` (new slot) or `PositionIncreased` (existing slot).
- **Refunded** → `PendingTradeRefund` with a reason code.

Poll [`getPositionsV4`](/onchain/reading-data#getpositionsv4) or subscribe to
[events](/onchain/events).

## Common reverts

| Error | Cause |
| :--- | :--- |
| `MarketClosed` / `PairClosed` | Outside trading hours, or the pair is disabled |
| `UnsupportedMarginToken` | `tokenIn` / `lvToken` mismatch |
| `InvalidAmount` | `amountIn` below the minimum, or below the open fee |
| `InsufficientLiquidityPool` | Pool cannot back the position size |
| `BelowDegenModeMinLeverage` | Resulting leverage below the pair's minimum |

Full list: [Error Reference](/reference/errors).
