# Build Order

> Build an EIP-712 order structure for a user to sign.

## Usage

```typescript
import { BuilderClient, OrderSide, OrderType } from '@opinion-labs/opinion-clob-sdk';

const builder = new BuilderClient({
  host: 'https://openapi.opinion.trade/openapi',
  builderApiKey: 'YOUR_BUILDER_KEY',
  chainId: 56,
});

const orderData = await builder.buildOrderForSigning({
  marketId: 123,
  tokenId: 'outcome_token_id',
  userWalletAddress: '0xSafeAddress...',   // User's Safe wallet (maker)
  side: OrderSide.BUY,
  orderType: OrderType.LIMIT_ORDER,
  amount: 10,
  price: '0.5',
  signerAddress: '0xEOAAddress...',        // User's EOA (signer)
});

console.log(orderData.order);            // Order struct (Record<string, string>)
console.log(orderData.structHash);       // Hash for signing
console.log(orderData.typedData);        // Full EIP-712 typed data
console.log(orderData.exchangeAddress);  // CTF Exchange address
console.log(orderData.currencyAddress);  // Quote token address
console.log(orderData.currencyDecimal);  // Token decimals
```

## Parameters

| Parameter           | Type      | Required  | Description                                                                                       |
| ------------------- | --------- | --------- | ------------------------------------------------------------------------------------------------- |
| `marketId`          | number    | Yes       | Market ID (positive integer)                                                                      |
| `tokenId`           | string    | Yes       | Outcome token ID                                                                                  |
| `userWalletAddress` | string    | Yes       | User's Safe wallet address (maker)                                                                |
| `side`              | OrderSide | Yes       | `OrderSide.BUY` (0) or `OrderSide.SELL` (1)                                                       |
| `orderType`         | OrderType | Yes       | `OrderType.LIMIT_ORDER` (2) or `OrderType.MARKET_ORDER` (1)                                       |
| `amount`            | number    | Yes       | Amount in human-readable units (e.g., 10 for 10 USDC)                                             |
| `price`             | string    | For limit | Price per outcome token (e.g., `'0.5'`). Required for limit orders.                               |
| `amountType`        | string    | No        | `'quote'` (default) or `'base'`. Quote = ERC20 amount, Base = token amount.                       |
| `signerAddress`     | string    | No        | Signer's EOA address. If different from `userWalletAddress`, Safe mode (signatureType=2) is used. |

## Response

```typescript
interface BuildOrderResult {
  order: Record<string, string>;    // Order struct fields
  structHash: string;               // EIP-712 struct hash for signing
  typedData: {                      // Full EIP-712 typed data
    types: Record<string, Array<{ name: string; type: string }>>;
    primaryType: string;
    domain: Record<string, unknown>;
    message: Record<string, unknown>;
  };
  domain: {
    name: string;                   // 'OPINION CTF Exchange'
    version: string;                // '1'
    chainId: number;
    verifyingContract: string;
  };
  exchangeAddress: string;
  currencyAddress: string;
  currencyDecimal: number;
  marketId: number;
  orderType: number;
  price: string;
}
```

## Signing the Order

**IMPORTANT**: Order signing uses `signHash(structHash)`, **not** `signTypedData`. This is different from Safe TX signing.

```typescript
// User signs the struct hash directly
const signature = await user.signHash(orderData.structHash);
```

### Test Helper

For testing, you can sign with a private key using the static helper:

```typescript
const signature = await BuilderClient.signOrderWithPrivateKey(
  orderData.typedData,
  '0xPrivateKey...'
);
```

> **Production**: Users sign with their own wallet (MetaMask, WalletConnect). The wallet should sign the `structHash` using `personal_sign` or equivalent.

## Notes

* For **limit orders**, `price` is required. For **market orders**, `price` is ignored.
* Market BUY orders only accept `amountType: 'quote'` (how much to spend).
* Market SELL orders only accept `amountType: 'base'` (how many tokens to sell).
* When `signerAddress` differs from `userWalletAddress`, the SDK automatically sets `signatureType` to 2 (POLY\_GNOSIS\_SAFE).
* Orders expire 30 days from creation by default.
