Authority split

Who owns what at the exchange edge

Identity · Privy

Provisions and signs

Privy owns the user-owned master wallet and the Privy-managed execution wallet. It signs ordinary Hyperliquid actions through a named agent. No private key reaches the harness, the T3 client, or any prompt.

Exchange · Hyperliquid

Holds the only truth

Hyperliquid owns canonical market metadata, account state, orders, fills, positions, margin, funding, and PnL. Local records are reconciled against it, never ranked above it.

Platform · T3 server

Validates and submits

The T3 server owns deterministic validation, nonce coordination, signing coordination, order submission, reconciliation, and the protective-order invariant. It never invents strategy.

Risk · Authority

Enforces the invariant

Every position-increasing action must include stop information before submission, and no acknowledged increase may remain unprotected past the reconciliation window.

Harness · Model

Requests, never signs

Codex, Claude, or OpenCode requests typed actions through the shared tool surface. The harness never sees credentials, raw payloads, or the signing boundary.

User · Human

Approves once

The user approves the Privy-backed Hyperliquid API wallet a single time. After approval, ordinary trading actions need no per-order prompt; risk-reducing buttons never depend on the harness.

§15.1 · Wallet model

One approval, then ordinary trading signatures

Privy userauthenticated identity
User-owned master walletHyperliquid master account
One-time approveAgentnamed Hyperliquid agent
Privy-managed execution walletordinary trading signatures
Hyperliquidaccount · orders · fills

Account state is always queried with the master-wallet address. The execution wallet is a signing mechanism for the master account, not a separate trading account, and must never be passed to account-query endpoints.

Execution wallet contract

Privy
  • Holds no separate trading capital.
  • Signs ordinary exchange actions for the master account.
  • Is registered under a named Hyperliquid agent.
  • Is never exposed to the harness as a private key.
  • Is replaced, not reused, after revocation.

Suggested agent name

T3 server
t3-trades-poc

The execution wallet is approved once under this agent name. Revocation creates a new wallet and a new approval rather than reusing the prior signing identity.

§15.2 · Hyperliquid gateway

One adapter shared by every provider

All providers reach Hyperliquid through the same HyperliquidGateway interface. No provider-specific exchange client is permitted: Codex, Claude, and OpenCode converge on identical market reads, account reads, and submission paths.

HyperliquidGateway

Hyperliquid
interface HyperliquidGateway {
  resolveMarket(symbol: string): Promise<ResolvedMarket>;
  getMarketSnapshot(market: string): Promise<MarketSnapshot>;
  getMarketHistory(input: MarketHistoryRequest): Promise<MarketHistory>;
  getAccountSnapshot(address: `0x${string}`): Promise<AccountSnapshot>;
  getOpenOrders(address: `0x${string}`): Promise<CanonicalOrder[]>;
  getOrderStatus(
    address: `0x${string}`,
    oidOrCloid: string,
  ): Promise<OrderStatus>;
  submit(action: NormalizedTradingAction): Promise<ExchangeSubmissionResult>;
}

address is always the master-wallet address, never the execution-wallet address. submit accepts a normalized action, not a raw Hyperliquid payload.

§15.3 · Market resolution and precision

Resolve metadata; never hard-code the asset index

Resolve and cache

Exchange
  • Canonical symbol
  • Asset index
  • Size decimals (szDecimals)
  • Maximum exchange leverage
  • Market availability

Before signing

Exchange
  • Normalize size to szDecimals.
  • Normalize price to Hyperliquid constraints.
  • Remove trailing zeroes.
  • Verify exchange minimum notional.
  • Return normalized values in the preview.

For the ETH-only proof of concept the ETH asset index is resolved at runtime from perp metadata, not copied into source. A metadata change on testnet must not silently break signing.

§15.4 · Market-like orders

Marketable IOC limits off a fresh book, never a stale mark

Marketable IOC construction

Exchange
Buy IOC limit  = fresh best ask + allowed slippage
Sell IOC limit = fresh best bid - allowed slippage
Do not derive the limit from a stale mark price. The mark is an indicative reference. A marketable IOC must be priced off a fresh best bid or best ask so that it actually crosses and fills, or cancels immediately. Execution-critical stale BBO blocks submission.

§15.5 · Client order IDs and idempotency

Deterministic cloid makes retries safe

16-byte cloid derivation

Authority
cloid = derive16Bytes(
  missionId,
  strategyVersion,
  executionSequence,
  actionType,
)
  • Persist the execution record before submission.
  • Retries reuse the same cloid and idempotency key.
  • A retry can never duplicate the order on the exchange.

§15.6 · Nonce coordination

One serialized nonce lane for the execution wallet

All actions signed by the execution wallet pass through one serialized nonce lane. The coordinator:

Issues

  • Monotonic nonces.
  • Fast-forward to current Unix milliseconds when necessary.

Guarantees

  • Never issues duplicates.
  • Persists the latest issued value as a recovery hint.
  • Serializes signing and submission for the wallet.

Because the lane is serialized, two harness-requested actions can never race for the same nonce, and a T3 restart can rehydrate the last issued value before submitting again.

§17 · Protective-order invariant

No acknowledged increase stays unprotected

Target invariant

No acknowledged position increase may remain without confirmed exchange-native reduce-only protection beyond the shortest technically necessary reconciliation window.

Any position increase must include stop information before submission. The invariant is confirmed from exchange state, not inferred from a grouped response or a local record.

§17.1 · Hyperliquid behavior to respect

A grouped response is not proof every order is live

Hyperliquid's order action accepts multiple orders and a grouping value of na, normalTpsl, or positionTpsl. A grouped submission is useful for expressing TP/SL relationships, but the HTTP response or the presence of a group is not proof that every requested order is live.

Parent-linked TP/SL partial-fill behavior

Exchange
  • If the parent fully fills, the child TP/SL orders are placed.
  • While the parent is unfilled or partially filled, its children may remain untriggered rather than live protective orders.
  • If a partially filled parent is manually canceled, its children are canceled; the partially filled position must be protected separately.
  • Hyperliquid documents an insufficient-margin special case where children may be placed as if the parent fully filled. T3 must still reconcile canonical state rather than infer protection from the cancellation reason.

Conclusion

Authority

A parent-linked normalTpsl request is an optimization and linkage mechanism. It is not the final safety invariant.

Never treat a batch as atomic. Inspect every returned per-order status. A grouped normalTpsl request that returns 200 can still contain a rejected child, an untriggered child, or a child canceled by parent cancellation. Confirm protection from canonical exchange state before marking an execution protected.

§17.2 · Marketable IOC entry path

Ten steps from preview to confirmed protection

  1. Validate. The harness requests a preview containing entry and stop information. T3 validates authority, precision, BBO freshness, loss reservations, and stop direction.
  2. Persist before signing. T3 persists the execution record and risk reservation before signing.
  3. Submit the grouped action. T3 may submit the IOC parent and linked TP/SL children in one normalTpsl order action after that exact request shape passes testnet validation.
  4. Inspect every per-order status. T3 does not assume batch atomicity. Each returned status is recorded.
  5. Query canonical state. T3 immediately queries canonical fills, position state, and open orders using the master-account address.
  6. Reconcile protection. If the canonical position is non-zero and confirmed protected size is smaller than the position, T3 immediately places or replaces exchange-native reduce-only stop protection for the actual canonical position. The validated implementation may use positionTpsl behavior or an explicitly sized reduce-only trigger order.
  7. Confirm protection. T3 confirms trigger direction, reduce-only status, market, and protected size from exchange state.
  8. Mark protected. Only then is the execution marked protected.
  9. Escalate on timeout. If full protection cannot be confirmed within the bounded reconciliation window, T3 cancels position-increasing orders and begins the deterministic emergency-close procedure.
  10. Never shortcut. A 200 response, a present group, or a locally recorded child never substitutes for canonical confirmation.

§17.3 · Resting GTC entry path

A partial fill must never be left exposed by its linked children

A resting parent may use linked normalTpsl children, but T3 must subscribe to parent fills and order updates. On any partial fill:

  1. Read the canonical position.
  2. Determine whether the filled size has live reduce-only stop coverage.
  3. Place separate protection for any uncovered filled size.
  4. Before manually canceling the remaining parent quantity, ensure the existing partial position has independent confirmed protection.
  5. Reconcile again after cancellation because parent-linked children may be canceled with the parent.
Never assume linkage protects a partial. A partially filled resting order must never be left exposed merely because linked children were included in the original request. While the parent is partial, those children may be untriggered; canceling the parent can cancel the children and leave the filled slice without a stop.

§17.4 · Scale-in and protection replacement

Resize protection to the canonical net position

After any scale-in fill:

  1. Read the canonical net ETH position.
  2. Calculate the required protected size and stop direction.
  3. Place or replace protection for the canonical position.
  4. Confirm the replacement before canceling the last known valid stop whenever the exchange path permits overlapping reduce-only protection safely.
  5. Never assume that a previously placed fixed-size trigger automatically resized.

§17.5 · Emergency-close procedure

A deterministic safety action, not a strategy decision

The emergency close is invoked when full protection cannot be confirmed within the bounded reconciliation window. It runs without the harness.

  1. Mark the mission blocked and block all position increases.
  2. Cancel mission-owned non-reduce-only entry and scale-in orders.
  3. Read fresh canonical position and BBO state.
  4. Submit a reduce-only marketable IOC order for the current position size.
  5. Reconcile fills and the remaining position.
  6. Retry with a fresh BBO and remaining size for at most three bounded attempts.
  7. If a position remains, preserve or re-establish any valid protection that can be placed, keep the mission blocked, and notify the user with the exact remaining size and failure reason.
Never rely on a later harness wake-up. The system must never depend on the harness waking later to place the primary stop or to complete an emergency close. The deterministic path must converge on its own.

§17.6 · Required testnet evidence

The matrix that must pass before the path is called complete

Before the protection path is considered complete, record testnet results for:

  • Fully filled IOC with linked TP/SL.
  • Partially filled IOC.
  • Resting parent with a partial fill.
  • Manual cancellation after a partial fill.
  • Insufficient-margin cancellation behavior.
  • Per-order rejection inside a multi-order action.
  • Stop trigger placement and confirmation.
  • Stop replacement after scale-in.
  • WebSocket loss during the protection window.
  • T3 restart during the protection window.
  • Emergency close with a partial IOC fill.
No mainnet claim from API shape alone. Documentation establishes intended Hyperliquid behavior; testnet evidence establishes that the exact SDK and request path used by T3 implements it correctly. The matrix above must pass before any mainnet assertion.

Hyperliquid research grounding

Official documentation that grounds this revision

Info endpoint

Documented candle intervals, candle history behavior, order status, and userFees.

Exchange endpoint

Multi-order actions, per-order statuses, normalTpsl, positionTpsl, reduce-only orders, modification, cancellation, and API-wallet actions.

Fees

Current fee model and use of the user-specific fee response.

The exact client library and request shape selected during implementation must still be validated on Hyperliquid testnet. Documentation establishes the intended API behavior; testnet evidence establishes that the T3 integration implements it correctly.