> ## Documentation Index
> Fetch the complete documentation index at: https://docs.outcome.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# HIP-4 SDK quickstart: install, authenticate, and trade

> Install the HIP-4 SDK, fetch live prediction markets, authenticate with an agent key, and place your first order on Outcome - five steps end-to-end.

This guide walks you through the full integration path, meaning that by the end, you'll have a working adapter, a list of available markets, and order submissions functional and verifiable (via the Hyperliquid exchange).

<Tip>
  Use `testnet: true` while you're getting started. The Hyperliquid testnet gives you a free environment to experiment without risking real funds.
</Tip>

<Steps>
  <Step title="Install the SDK">
    Add `@outcome.xyz/hip4` to your project:

    ```bash theme={null}
    pnpm add @outcome.xyz/hip4
    ```
  </Step>

  <Step title="Create and initialize the adapter">
    Import `createHIP4Adapter` and call `initialize()` to warm up the event cache. Every other SDK method depends on this step completing first.

    ```typescript theme={null}
    import { createHIP4Adapter } from "@outcome.xyz/hip4";

    const hip4 = createHIP4Adapter({ testnet: true });
    await hip4.initialize();
    ```

    The adapter automatically connects to the correct Hyperliquid testnet endpoints for both REST and WebSocket traffic. Switch to `{ testnet: false }` when you're ready for mainnet.
  </Step>

  <Step title="Fetch markets">
    Call `fetchMarkets()` to retrieve live prediction markets. The response is an array of typed market objects - each one carries pre-computed side identifiers, expiry dates, and outcome metadata.

    ```typescript theme={null}
    import type { DefaultBinaryMarket } from "@outcome.xyz/hip4";

    const markets = (await hip4.events.fetchMarkets({
      type: "defaultBinary",
    })) as DefaultBinaryMarket[];

    for (const market of markets) {
      console.log(market.underlying); // "BTC"
      console.log(market.targetPrice); // 69070
      console.log(market.expiry); // Date object
      console.log(market.period); // "1d"
      console.log(market.sides[0].coin); // "#5160"  (Yes side)
      console.log(market.sides[1].name); // "No"
    }
    ```

    `defaultBinary` markets are recurring price binary markets (e.g. "Will BTC be above \$69,070 at expiry?"). You can also filter by `"labelledBinary"` or `"multiOutcome"`, or omit the `type` filter to get all markets.
  </Step>

  <Step title="Set up authentication">
    Trading requires an approved ephemeral agent key. The agent key signs orders on your behalf without exposing your main wallet's private key. The approval flow is a one-time operation per agent.

    ```typescript theme={null}
    import {
      getAgentApprovalTypedData,
      submitAgentApproval,
    } from "@outcome.xyz/hip4";
    import { createWalletClient, http } from "viem";
    import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
    import { arbitrum } from "viem/chains";

    // Your user's main wallet (from environment - never hardcode private keys)
    const userAccount = privateKeyToAccount(
      process.env.PRIVATE_KEY as `0x${string}`,
    );
    const walletClient = createWalletClient({
      account: userAccount,
      chain: arbitrum,
      transport: http(),
    });

    // Generate a fresh ephemeral agent key
    const agentPrivateKey = generatePrivateKey();
    const agentAccount = privateKeyToAccount(agentPrivateKey);

    // Build the EIP-712 approval payload and have the user sign it
    const nonce = Date.now();
    const typedData = getAgentApprovalTypedData(
      agentAccount.address,
      "My App",
      nonce,
      false, // false = testnet
    );

    const signature = await walletClient.signTypedData({
      domain: typedData.domain,
      types: typedData.types,
      primaryType: typedData.primaryType,
      message: typedData.message,
    });

    // Submit the approval to the Hyperliquid exchange
    const approval = await submitAgentApproval(
      signature,
      agentAccount.address,
      "My App",
      nonce,
      false, // false = testnet
    );

    if (!approval.success) {
      throw new Error(`Agent approval failed: ${approval.error}`);
    }

    // Initialize the adapter with the approved agent
    await hip4.auth.initAuth(userAccount.address, agentAccount);

    console.log(hip4.auth.getAuthStatus().status); // "ready"
    ```

    After `initAuth()` completes, the adapter signs all subsequent orders automatically using the agent key.
  </Step>

  <Step title="Place a limit order">
    With auth initialized, call `hip4.trading.placeOrder()` to submit a limit order. The method returns a result object - it never throws.

    <Warning>
      Placing orders on mainnet (`testnet: false`) uses real funds. Make sure your account has sufficient USDH balance before submitting.
    </Warning>

    ```typescript theme={null}
    import { getMinShares } from "@outcome.xyz/hip4";
    import type { DefaultBinaryMarket } from "@outcome.xyz/hip4";

    // Pick a market (reusing the list from step 3)
    const market = markets[0] as DefaultBinaryMarket;

    // Fetch the current mid price for min-shares validation
    const priceData = await hip4.marketData.fetchPrice(String(market.outcomeId));
    const markPx = parseFloat(priceData.outcomes[0]?.midpoint ?? "0.5");

    // Place a limit buy on the Yes side
    const result = await hip4.trading.placeOrder({
      marketId: String(market.outcomeId),
      outcome: market.sides[0].coin, // Yes side coin, e.g. "#5160"
      side: "buy",
      type: "limit",
      price: String(markPx),
      amount: String(getMinShares(markPx)), // minimum shares for 10 USDH notional
      markPx, // enables pre-submission min-shares check
    });

    if (result.success) {
      console.log("Order status:", result.status);
      if (result.orderId) console.log("Order ID:", result.orderId);
      if (result.shares) console.log("Filled shares:", result.shares);
    } else {
      console.error("Order rejected:", result.error);
    }
    ```

    `getMinShares(markPx)` computes the minimum number of shares required to meet the 10 USDH notional floor at the given price. Passing `markPx` to `placeOrder` enables the SDK to validate this before signing and submitting.
  </Step>
</Steps>

## Next steps

* Read the [core concepts](/sdk/concepts/markets) to understand market types, coin naming, and the two signing flows.
* See the [trading guide](/sdk/guides/trading) for market orders, cancellations, and builder fee configuration.
* Explore the [real-time data guide](/sdk/guides/real-time-data) to subscribe to live order books and price streams.
