Market Orders
Open a position at the current oracle price.
openMarketTradeV2
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.
OpenDataInput
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. Do not hardcode. |
tokenIn / lvToken | Must be a valid pair — see the table. |
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. |
broker | Referral channel for this trade's fee. 0 credits the default broker, not "no broker" — see Brokers & Referrals. |
updateData and extraFee
updateData is the oracle payload from POST /v1/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 coveramountIn + extraFee. - It goes to the receiver of whatever
brokerid you passed — pairingextraFee > 0withbroker: 0pays the default broker, not you. - It is returned along with the collateral if the open is refunded.
See Brokers & Referrals.
Example
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:
const worstPrice = parseUnits((markPrice * (1 - slippagePct / 100)).toFixed(18), 18)Using native MON as collateral
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) orPositionIncreased(existing slot). - Refunded →
PendingTradeRefundwith a reason code.
Poll getPositionsV4 or subscribe to 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.