# Builder Mode

> Build your own trading terminal on top of Opinion's prediction market with non-custodial user management and 2,000 free gasless transactions per day.
>
> To request Builder access, Please kindly fill out this [short application form ](https://forms.gle/tqL84A5mMXjZ1xT86).&#x20;

## Overview

Builder mode lets platforms manage user sub-accounts and place orders on behalf of users. Users retain control of their funds through Gnosis Safe wallets and sign all operations with their own keys.

## Architecture

```
┌──────────────┐     ┌──────────────────┐     ┌────────────┐
│  Your App    │     │  Opinion Backend  │     │  BNB Chain  │
│  (Builder)   │────>│  (API + Relayer)  │────>│  (On-chain) │
│              │     │                   │     │             │
│  BuilderClient     │  - Order matching │     │  - Safe     │
│  + UserClient│<────│  - TX relay       │<────│  - CTF      │
│              │     │  - Safe creation  │     │  - ERC20    │
└──────────────┘     └──────────────────┘     └────────────┘
```

**Three wallets involved:**

| Wallet                  | What                               | Who Controls             |
| ----------------------- | ---------------------------------- | ------------------------ |
| **EOA** (signer)        | Signs orders and Safe transactions | User (private key)       |
| **Safe** (asset wallet) | Holds funds, executes trades       | Multi-sig (EOA is owner) |
| **Builder API key**     | Authenticates builder API calls    | Builder (your server)    |

## Quick Start

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

// 1. Initialize builder client
const builder = new BuilderClient({
  host: 'https://openapi.opinion.trade/openapi',
  builderApiKey: 'YOUR_BUILDER_KEY',
  chainId: 56,
  rpcUrl: 'https://bsc-dataseed.binance.org',
});

// 2. Create a user and save the API key
const userInfo = await builder.createUser('0xUserEOA...');
const userApiKey = userInfo.apikey; // SAVE THIS - only returned once!

// 3. Build and sign an order
const orderData = await builder.buildOrderForSigning({
  marketId: 123,
  tokenId: 'token_id',
  userWalletAddress: userInfo.multiSigWallet,
  side: OrderSide.BUY,
  orderType: OrderType.LIMIT_ORDER,
  amount: 10,
  price: '0.5',
  signerAddress: '0xUserEOA...',
});

// 4. User signs the order hash (in production, use MetaMask/WalletConnect)
const user = new UserClient('0xUserPrivateKey...');
const signature = await user.signHash(orderData.structHash);

// 5. Place order
const result = await builder.placeOrderForUserFromBuildResult(
  orderData, signature, userInfo.multiSigWallet
);
```

## Configuration

```typescript
const builder = new BuilderClient({
  host: 'https://openapi.opinion.trade/openapi',
  builderApiKey: 'YOUR_BUILDER_KEY',
  chainId: 56,
  rpcUrl: 'https://bsc-dataseed.binance.org',  // Required for Safe operations
  proxyUrl: 'http://127.0.0.1:7890',           // Optional HTTP proxy
  quoteTokensCacheTtl: 3600,                    // Cache TTL in seconds (default: 3600)
  marketCacheTtl: 300,                          // Cache TTL in seconds (default: 300)
});
```

| Parameter             | Type    | Required | Description                                           |
| --------------------- | ------- | -------- | ----------------------------------------------------- |
| `host`                | string  | Yes      | API host URL                                          |
| `builderApiKey`       | string  | Yes      | Builder API key (uses `builder-apikey` header)        |
| `chainId`             | number  | Yes      | Blockchain chain ID (56 for BNB Chain)                |
| `rpcUrl`              | string  | No       | RPC endpoint URL (required for Safe operations)       |
| `proxyUrl`            | string  | No       | HTTP proxy URL for API requests                       |
| `useBeta`             | boolean | No       | Use beta/testnet addresses (default: false)           |
| `contractAddresses`   | object  | No       | Override specific contract addresses                  |
| `quoteTokensCacheTtl` | number  | No       | Cache TTL for quote tokens in seconds (default: 3600) |
| `marketCacheTtl`      | number  | No       | Cache TTL for market data in seconds (default: 300)   |

## API Reference

### User Management

* [Create User](https://docs.opinion.trade/developer-guide/opinion-clob-typescript-sdk/builder-mode/create-user) -- register a sub-account and get an API key
* [Get User / Regenerate API Key](https://docs.opinion.trade/developer-guide/opinion-clob-typescript-sdk/builder-mode/get-user) -- query user info or regenerate credentials

### Market Data

* [Get Quote Tokens](https://docs.opinion.trade/developer-guide/opinion-clob-typescript-sdk/builder-mode/get-quote-tokens) -- list supported currencies
* [Get Market / Orderbook](https://docs.opinion.trade/developer-guide/opinion-clob-typescript-sdk/builder-mode/get-market) -- query market details and orderbook depth

### Trading

* [Build Order](https://docs.opinion.trade/developer-guide/opinion-clob-typescript-sdk/builder-mode/build-order) -- build an EIP-712 order structure for signing
* [Place Order](https://docs.opinion.trade/developer-guide/opinion-clob-typescript-sdk/builder-mode/place-order) -- submit a signed order on behalf of a user
* [Cancel / Manage Orders](https://docs.opinion.trade/developer-guide/opinion-clob-typescript-sdk/builder-mode/cancel-order) -- cancel orders and query order history

### On-chain Operations

* [Enable Trading](https://docs.opinion.trade/developer-guide/opinion-clob-typescript-sdk/builder-mode/enable-trading) -- one-time approval setup via Safe transaction
* [Split / Merge / Redeem / Withdraw](https://docs.opinion.trade/developer-guide/opinion-clob-typescript-sdk/builder-mode/split-merge-redeem) -- token operations via Safe transactions

### Testing

* [UserClient](https://docs.opinion.trade/developer-guide/opinion-clob-typescript-sdk/builder-mode/userclient) -- test wallet helper for signing

## Error Handling

```typescript
import {
  BuilderError,
  BuilderInvalidParamError,
  BuilderApiError,
} from '@opinion-labs/opinion-clob-sdk';

try {
  await builder.createUser(address);
} catch (e) {
  if (e instanceof BuilderInvalidParamError) {
    // Bad input: invalid address format, missing required field
    console.error('Invalid parameter:', e.message);
  } else if (e instanceof BuilderApiError) {
    // Backend error: user already exists, rate limit, server error
    console.error('API error:', e.message);
  } else if (e instanceof BuilderError) {
    // General builder error (base class)
    console.error('Builder error:', e.message);
  }
}
```

## Signature Types

| Type               | Value | Description                             |
| ------------------ | ----- | --------------------------------------- |
| EOA                | 0     | Direct EOA signature (maker == signer)  |
| POLY\_GNOSIS\_SAFE | 2     | Gnosis Safe signature (maker != signer) |

The signature type is automatically determined based on whether `signerAddress` differs from `userWalletAddress` in `buildOrderForSigning()`.
