> ## 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 Utilities: Pricing, Coins, and Orderbook

> Pure utility functions from @outcome.xyz/hip4 for tick-aligned pricing, market discovery, coin name encoding, cost estimation, and price feed streams.

The SDK exports a set of standalone utility functions alongside the main adapter. These functions have no side effects and no dependency on an initialized adapter instance - import and call them directly. They cover four areas: tick-aligned price formatting, market discovery and classification, coin name encoding, and orderbook cost estimation. Two stream constructors for live chart feeds are also covered here.

## Pricing utilities

These functions handle Hyperliquid's magnitude-based decimal precision and minimum order size constraints.

### `computeTickSize(price)`

Returns the tick size for a given price using 5 significant figures.

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

computeTickSize(0.55);    // 0.00001
computeTickSize(1.25);    // 0.0001
computeTickSize(100);     // 0.001
```

### `roundToTick(price)`

Rounds a price to the nearest tick boundary.

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

roundToTick(0.55123);    // 0.5512 (rounded to nearest 0.0001)
```

### `formatPrice(price)`

Formats a price as a tick-aligned string with trailing zeros stripped. Prices below 1 receive 4 decimal places.

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

formatPrice(0.5500);     // "0.55"
formatPrice(0.6512);     // "0.6512"
formatPrice(1.20);       // "1.2"
```

### `stripZeros(str)`

Removes trailing zeros from a numeric string.

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

stripZeros("0.65000");   // "0.65"
stripZeros("1.0000");    // "1"
```

### `getMinShares(markPx)`

Returns the minimum number of shares required to meet the 10 USDH minimum notional for a given mark price.

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

getMinShares(0.65);    // 29
getMinShares(0.10);    // 100
```

### `MIN_NOTIONAL`

The minimum order size in USDH. Currently `10`. Orders below this threshold are rejected before submission.

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

console.log(MIN_NOTIONAL);   // 10
```

## Market discovery

These functions help you find and describe recurring HIP-4 markets from raw metadata.

### `parseDescription(desc)`

Parses a pipe-delimited recurring market description string into a structured object.

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

parseDescription(
  "class:priceBinary|underlying:BTC|expiry:20260311-0300|targetPrice:69070|period:1d"
);
// {
//   class: "priceBinary",
//   underlying: "BTC",
//   expiry: Date,         // parsed UTC Date
//   targetPrice: 69070,
//   period: "1d"
// }
```

### `discoverPriceBinaryMarkets(meta)`

Scans raw `outcomeMeta` and returns all outcomes that are recurring price binary markets.

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

const markets = discoverPriceBinaryMarkets(outcomeMeta);
```

### `periodMinutes(period)`

Converts a period string to its equivalent number of minutes.

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

periodMinutes("1d");    // 1440
periodMinutes("1h");    // 60
periodMinutes("15m");   // 15
```

### `formatMarketLabel(market)`

Returns a short human-readable label for a market, combining the underlying asset and period.

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

formatMarketLabel(market);    // "BTC-1d"
```

### `timeToExpiry(expiry)`

Returns a human-readable string describing how long until a market expires.

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

timeToExpiry(new Date("2026-03-11T03:00:00Z"));    // "2h 34m"
```

## Market classification

These functions classify raw HIP-4 outcomes into typed `HIP4Market` objects.

### `classifyOutcome(outcome, questions)`

Classifies a single outcome from the raw API response. Returns a `HIP4Market` with the appropriate `type` discriminant.

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

const market = classifyOutcome(outcome, questions);
// market.type === "defaultBinary" | "labelledBinary" | "multiOutcome" | "priceBucket"
```

### `classifyAllOutcomes(meta)`

Classifies all outcomes from a full `outcomeMeta` response. Returns an array of `HIP4Market` objects.

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

const markets = classifyAllOutcomes(outcomeMeta);
```

## Coin helpers

HIP-4 uses a specific coin naming convention for order book lookups and order placement. These helpers encode and decode those identifiers.

| Helper                              | Example output                     | Description                            |
| ----------------------------------- | ---------------------------------- | -------------------------------------- |
| `sideCoin(outcomeId, sideIndex)`    | `"#5160"`                          | Tradeable side coin string             |
| `sideAssetId(outcomeId, sideIndex)` | `100005160`                        | Numeric asset ID for order wire format |
| `parseSideCoin(coin)`               | `{ outcomeId: 516, sideIndex: 0 }` | Decode a side coin string              |
| `outcomeCoin(outcomeId)`            | `"@516"`                           | Outcome-level coin for price lookups   |

```typescript theme={null}
import { sideCoin, sideAssetId, parseSideCoin, outcomeCoin } from "@outcome.xyz/hip4"
sideCoin(516, 0);          // "#5160"
sideCoin(516, 1);          // "#5161"
sideAssetId(516, 0);       // 100005160
parseSideCoin("#5160");    // { outcomeId: 516, sideIndex: 0 }
parseSideCoin("invalid");  // null
outcomeCoin(516);          // "@516"
```

<Note>
  Use `sideCoin` output (e.g. `"#5160"`) as the `outcome` field when calling `hip4.trading.placeOrder`. Use `outcomeCoin` output (e.g. `"@516"`) for price lookups via `hip4.marketData.fetchPrice`.
</Note>

## Orderbook utilities

These functions estimate trade cost and potential return from token amounts and prices. Prices are expressed in cents (0–100 range) internally.

### `computeEstimatedCost(tokenAmount, orderType, limitPriceCents, marketPriceCents?)`

Estimates the USDH cost for a given token amount. For limit orders, uses `limitPriceCents`. For market orders, uses `marketPriceCents` when provided, otherwise returns `tokenAmount` as a fallback.

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

computeEstimatedCost(100, "limit", 65, undefined);     // 65 USDH
computeEstimatedCost(100, "market", null, 65);          // 65 USDH
```

### `computeTradeCost(params)`

Returns a `TradeCostResult` with all three values needed to display a trade preview.

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

const result: TradeCostResult = computeTradeCost({
  tokenAmount: 100,
  orderType: "limit",
  limitPriceCents: 65,
  marketPriceCents: undefined,
});
// {
//   estimatedCost: 65,       // USDH to spend
//   potentialReturn: 100,    // max payout (= tokenAmount)
//   displayShares: 100,      // shares to show in UI
// }
```

### `computePotentialReturn(tokenAmount)`

Returns the maximum payout for a given number of shares. Each share pays 1 USDH if the outcome resolves in your favor.

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

computePotentialReturn(100);    // 100
computePotentialReturn(0);      // 0
```

## Price feed streams

These constructors create continuously-updating chart feeds by merging historical candle data with real-time WebSocket ticks.

### `createPriceFeed(marketData, marketId, onSnapshot, options?)`

Creates a live price feed for a single prediction market outcome. Returns an unsubscribe function.

```typescript theme={null}
import { createPriceFeed } from "@outcome.xyz/hip4";
import type { PriceFeedSnapshot, PriceFeedOptions } from "@outcome.xyz/hip4";

const options: PriceFeedOptions = {
  interval: "1h",          // candle interval; default "1h"
  lookbackMs: 7 * 24 * 60 * 60 * 1000,   // 7 days lookback; default 14 days
  sideIndex: 0,            // 0 = Yes side, 1 = No side; default 0
};

const unsub = createPriceFeed(
  hip4.marketData,
  "516",
  (snapshot: PriceFeedSnapshot) => {
    if (!snapshot.ready) return;
    renderChart(snapshot.candles);
    updateMidPrice(snapshot.currentMid);
  },
  options,
);

// Stop the feed when done
unsub();
```

`PriceFeedSnapshot` fields:

| Field        | Type                | Description                                                 |                                                          |
| ------------ | ------------------- | ----------------------------------------------------------- | -------------------------------------------------------- |
| `marketId`   | `string`            | The market ID passed to the constructor                     |                                                          |
| `candles`    | `PriceFeedCandle[]` | Full candle array (historical + live updates)               |                                                          |
| `currentMid` | \`number            | null\`                                                      | Latest mid-price tick; may be newer than the last candle |
| `ready`      | `boolean`           | `false` until the initial historical candle fetch completes |                                                          |

### `createPerpPriceFeed(client, coin, onSnapshot, options?)`

Creates a live price feed for a perpetual market coin (e.g. `"BTC"`, `"ETH"`). Uses the `candle` WebSocket channel for authoritative OHLCV data and `allMids` for the initial mid-price.

```typescript theme={null}
import { HIP4Client, createPerpPriceFeed } from "@outcome.xyz/hip4";
import type { PerpPriceFeedSnapshot } from "@outcome.xyz/hip4";

const unsub = createPerpPriceFeed(
  hip4Client,
  "BTC",
  (snapshot: PerpPriceFeedSnapshot) => {
    if (!snapshot.ready) return;
    renderChart(snapshot.candles);
  },
  { interval: "1h", lookbackMs: 14 * 24 * 60 * 60 * 1000 },
);

unsub();
```

`PerpPriceFeedSnapshot` differs from `PriceFeedSnapshot` in its `coin` field (instead of `marketId`).
