# Create Order

## Create Order API

This guide explains how to programmatically create orders on the DMEX exchange.

### Overview

Orders are created by:

1. Building the order parameters
2. Generating a keccak256 hash of the order
3. Signing the hash with your private key
4. Sending the signed order via WebSocket

### Order Parameters

| Parameter       | Type    | Description                                       |
| --------------- | ------- | ------------------------------------------------- |
| `amount`        | string  | Order size (will be multiplied by 1e8)            |
| `price`         | string  | Order price (will be multiplied by 1e8)           |
| `side`          | boolean | `true` = buy/long, `false` = sell/short           |
| `leverage`      | string  | Leverage multiplier (e.g., "10" for 10x)          |
| `base_token`    | address | The margin token contract address                 |
| `asset`         | string  | Trading pair symbol (e.g., "BTC", "ETH")          |
| `closing_order` | boolean | `true` if this order closes an existing position  |
| `stop`          | boolean | `true` if this is a stop order                    |
| `stop_price`    | string  | Trigger price for stop orders (multiplied by 1e8) |
| `is_market`     | boolean | `true` for market orders                          |
| `post_only`     | boolean | `true` to ensure order is maker only              |
| `replace_hash`  | string  | Hash of order to replace, or zero hash            |

### JavaScript/TypeScript Example

```typescript
import { ethers } from 'ethers';
import Web3 from 'web3';

// Configuration
const WS_ENDPOINT = 'wss://api.dmex.app/ws';
const BASE_TOKEN = '0x...'; // USDC or other margin token address

async function createOrder({
    privateKey,
    asset,
    amount,
    price,
    side,
    leverage,
    closingOrder = false,
    stop = false,
    stopPrice = '0',
    isMarket = false,
    postOnly = false,
    replaceHash = ''
}: {
    privateKey: string;
    asset: string;
    amount: string;
    price: string;
    side: boolean;
    leverage: string;
    closingOrder?: boolean;
    stop?: boolean;
    stopPrice?: string;
    isMarket?: boolean;
    postOnly?: boolean;
    replaceHash?: string;
}) {
    // Initialize web3 for signing
    const web3 = new Web3();
    const account = web3.eth.accounts.privateKeyToAccount(privateKey);
    const userAddress = account.address;

    // Convert to 1e8 precision
    const amountScaled = (Number(amount) * 1e8).toFixed(0);
    const priceScaled = (Number(price) * 1e8).toFixed(0);
    const stopPriceScaled = (Number(stopPrice) * 1e8).toFixed(0);

    // Generate unique nonce
    const nonce = Date.now();

    // Create order hash
    const orderHash = ethers.utils.keccak256(
        ethers.utils.defaultAbiCoder.encode(
            ['string', 'address', 'address', 'uint256', 'uint256', 'bool', 'uint256', 'uint256'],
            [asset, BASE_TOKEN, userAddress, amountScaled, priceScaled, side, nonce, leverage]
        )
    );

    // Sign the hash
    const signedData = web3.eth.accounts.sign(orderHash, privateKey);
    const signature = signedData.signature;

    // Parse signature into v, r, s
    const sig = signature.slice(2);
    const r = `0x${sig.slice(0, 64)}`;
    const s = `0x${sig.slice(64, 128)}`;
    let v = parseInt(`0x${sig.slice(128, 130)}`, 16);
    if (v < 27) v += 27;

    // Format replace_hash
    const formattedReplaceHash = replaceHash === '' 
        ? '0x0000000000000000000000000000000000000000000000000000000000000000'
        : replaceHash;

    // Build order payload
    const order = {
        hash: orderHash,
        user_address: userAddress,
        base_token: BASE_TOKEN,
        asset: asset,
        amount: amountScaled,
        price: priceScaled,
        side: side,
        nonce: nonce,
        leverage: leverage,
        closing_order: closingOrder,
        v: v,
        r: r,
        s: s,
        remaining_amount: amountScaled,
        closed: false,
        stop: stop,
        stop_price: stopPriceScaled,
        stopped: false,
        is_market: isMarket,
        replace_hash: formattedReplaceHash,
        post_only: postOnly
    };

    return order;
}

// Send order via WebSocket
function sendOrder(ws: WebSocket, order: object) {
    const message = JSON.stringify({
        op: 'create_order',
        data: order
    });
    ws.send(message);
}

// Usage Example
async function main() {
    const privateKey = '0x...'; // Your private key
    
    // Create a limit buy order for 0.1 BTC at $50,000 with 10x leverage
    const order = await createOrder({
        privateKey,
        asset: 'BTC',
        amount: '0.1',
        price: '50000',
        side: true,        // true = buy/long
        leverage: '10',
        closingOrder: false,
        isMarket: false,
        postOnly: false
    });

    // Connect to WebSocket and send
    const ws = new WebSocket(WS_ENDPOINT);
    
    ws.onopen = () => {
        console.log('Connected');
        sendOrder(ws, order);
    };

    ws.onmessage = (event) => {
        const response = JSON.parse(event.data);
        console.log('Response:', response);
    };
}
```

### Python Example

```python
import json
import time
import websocket
from web3 import Web3
from eth_abi import encode

# Configuration
WS_ENDPOINT = 'wss://api.dmex.app/ws'
BASE_TOKEN = '0x...'  # USDC or other margin token address

def create_order(
    private_key: str,
    asset: str,
    amount: str,
    price: str,
    side: bool,
    leverage: str,
    closing_order: bool = False,
    stop: bool = False,
    stop_price: str = '0',
    is_market: bool = False,
    post_only: bool = False,
    replace_hash: str = ''
):
    w3 = Web3()
    account = w3.eth.account.from_key(private_key)
    user_address = account.address

    # Convert to 1e8 precision
    amount_scaled = str(int(float(amount) * 1e8))
    price_scaled = str(int(float(price) * 1e8))
    stop_price_scaled = str(int(float(stop_price) * 1e8))

    # Generate unique nonce
    nonce = int(time.time() * 1000)

    # Create order hash
    encoded = encode(
        ['string', 'address', 'address', 'uint256', 'uint256', 'bool', 'uint256', 'uint256'],
        [asset, BASE_TOKEN, user_address, int(amount_scaled), int(price_scaled), side, nonce, int(leverage)]
    )
    order_hash = Web3.keccak(encoded).hex()

    # Sign the hash
    signed = w3.eth.account.sign_message(
        encode_defunct(hexstr=order_hash),
        private_key=private_key
    )
    
    v = signed.v
    r = hex(signed.r)
    s = hex(signed.s)

    # Format replace_hash
    formatted_replace_hash = (
        '0x0000000000000000000000000000000000000000000000000000000000000000'
        if replace_hash == '' else replace_hash
    )

    # Build order payload
    order = {
        'hash': order_hash,
        'user_address': user_address,
        'base_token': BASE_TOKEN,
        'asset': asset,
        'amount': amount_scaled,
        'price': price_scaled,
        'side': side,
        'nonce': nonce,
        'leverage': leverage,
        'closing_order': closing_order,
        'v': v,
        'r': r,
        's': s,
        'remaining_amount': amount_scaled,
        'closed': False,
        'stop': stop,
        'stop_price': stop_price_scaled,
        'stopped': False,
        'is_market': is_market,
        'replace_hash': formatted_replace_hash,
        'post_only': post_only
    }

    return order


def send_order(ws, order):
    message = json.dumps({
        'op': 'create_order',
        'data': order
    })
    ws.send(message)


# Usage Example
if __name__ == '__main__':
    from eth_account.messages import encode_defunct
    
    private_key = '0x...'  # Your private key
    
    # Create a limit buy order for 0.1 BTC at $50,000 with 10x leverage
    order = create_order(
        private_key=private_key,
        asset='BTC',
        amount='0.1',
        price='50000',
        side=True,  # True = buy/long
        leverage='10',
        closing_order=False,
        is_market=False,
        post_only=False
    )

    # Connect and send
    ws = websocket.create_connection(WS_ENDPOINT)
    send_order(ws, order)
    
    response = ws.recv()
    print('Response:', response)
    ws.close()
```

### Order Hash Structure

The order hash is generated using `keccak256` with ABI-encoded parameters:

```
keccak256(abi.encode(
    asset,        // string  - Trading pair symbol
    base_token,   // address - Margin token contract
    user_address, // address - Your wallet address
    amount,       // uint256 - Order size * 1e8
    price,        // uint256 - Order price * 1e8
    side,         // bool    - true=buy, false=sell
    nonce,        // uint256 - Unique timestamp
    leverage      // uint256 - Leverage multiplier
))
```

### Order Types

#### Limit Order

```typescript
{
    is_market: false,
    stop: false,
    post_only: false  // or true for maker-only
}
```

#### Market Order

```typescript
{
    is_market: true,
    stop: false
}
```

#### Stop-Limit Order

```typescript
{
    is_market: false,
    stop: true,
    stop_price: '49000'  // Trigger price
}
```

#### Stop-Market Order

```typescript
{
    is_market: true,
    stop: true,
    stop_price: '49000'
}
```

### Closing Positions

To close an existing position, set `closing_order: true`. The `side` should be opposite to your current position:

* To close a long position: `side: false` (sell)
* To close a short position: `side: true` (buy)

### Replacing Orders

To replace an existing order, pass the hash of the order you want to cancel in `replace_hash`. This atomically cancels the old order and creates the new one.

### Error Handling

Common validation errors:

* **Amount must be greater than zero**
* **Invalid signature** - Ensure the hash is signed correctly
* **Insufficient margin** - Not enough balance for the order
* **Invalid leverage** - Leverage outside allowed range for the asset

### WebSocket Response

Successful order creation returns:

```json
{
    "op": "order_created",
    "data": {
        "hash": "0x...",
        "status": "open"
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.dmex.app/api-docs/websocket/create-order.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
