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

# Trade perps with Yield.xyz

> Learn how to fund a trading account, open and manage leveraged perpetual-futures positions, and sign and submit the resulting transactions using the Enclave MPC API and the Yield.xyz integration.

Portal's Enclave MPC API lets your users trade perpetual futures on venues such as Hyperliquid through the Yield.xyz integration. This guide covers discovering venues and markets, funding a trading account, opening and managing leveraged positions, signing the transactions each action returns, and tracking positions, orders and history.

## Overview

The perps functionality allows you to:

* **Discover** the trading venues (providers) and the markets each offers, with live mark and oracle prices, funding rates, leverage ranges and fees
* **Fund** a trading account with collateral and complete any one-time venue approvals the API requires
* **Open** leveraged long or short positions and **close** them to realize PnL
* **Manage** risk with stop-loss / take-profit orders, and adjust leverage, margin and resting orders
* **Track** positions, orders and account balances, and a unified feed of trading activity and lifecycle events

A user funds a trading account, opens a position sized above that collateral by a chosen leverage, pays a periodic funding rate while it is open, and is liquidated if the price moves against the position far enough that its margin can no longer cover the loss. The [integration page](/integrations/Yield/yield-xyz-perps#how-perpetual-futures-trading-works) explains the mechanics and why you might offer it.

All endpoints live under `https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-perps` and return `{ "data": ... }`. Venues are identified by an opaque `providerId` (for example `hyperliquid`); real chains, where they appear, use [CAIP-2](/resources/chain-id-formatting) (`eip155:42161` for Arbitrum).

<Note>
  This guide uses **Hyperliquid** as the example venue, since it is the launch venue. Everything here is driven by the Yield.xyz Perps API, not hard-coded to Hyperliquid: a venue's supported actions, required approvals and per-action `args` come from `GET /providers` (`supportedActions` and `argumentSchemas`), and how you sign each transaction is dictated by the `signingFormat` the API returns on that transaction — not by which venue it is. Discover a venue's capabilities from the API and drive your integration from that, so a venue Yield.xyz adds later works with no code change.
</Note>

## Prerequisites

Before using perps operations, ensure you have:

* A properly initialized Portal client (see [Create a client](./create-a-client))
* An active wallet with **gas** on the funding chain (see [Create a wallet](./create-a-wallet))
* Yield.xyz integration enabled in your Portal Dashboard (see [Yield.xyz Perps](/integrations/Yield/yield-xyz-perps))
* Collateral (USDC) to fund the trading account — see [Funding a trading account](#funding-a-trading-account-and-approving-the-venue) below

<Warning>
  **There is no testnet for perps.** The Yield.xyz Perps API is production-only: there is no sandbox host and no testnet venue, and `POST /api/v3/clients/me/fund` (Portal's testnet faucet) does not apply. Every action is real money on mainnet. Validate with the venue's minimum notional (roughly \$10 on Hyperliquid), funded with real USDC. Perpetual futures are high-risk: leverage amplifies losses, and a position can be liquidated — losing its entire margin — within minutes.
</Warning>

<Warning>
  **Perps require a Portal client *without* [account abstraction](/resources/account-abstraction) (`isAccountAbstracted: false`).** An AA client's wallet is a smart-contract address, but Hyperliquid — the launch venue — verifies every action by recovering the signer from an EIP-712 signature and acts on the recovered EOA. A deposit from an AA wallet is therefore credited to an address that can never sign, so the funds can be neither traded nor withdrawn. Do not send perps write requests (`fund`, `open`, `close`, `withdraw` and the like) from an account-abstracted client.
</Warning>

## Discovering venues

Use the `GET /providers` endpoint to list the trading venues, the actions each supports, and the argument schema for each action.

```bash theme={null}
curl --request GET \
  --url 'https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-perps/providers' \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]'
```

Each provider carries an `id` (a venue slug such as `hyperliquid`, used unchanged as `providerId` everywhere else), a `supportedActions` list, and `argumentSchemas` — a JSON Schema per action describing the exact `args` that action accepts. Treat `argumentSchemas` as the source of truth for what each action needs on a given venue. Use `GET /providers/{providerId}` for one venue.

## Discovering markets

Use the `GET /markets` endpoint to list tradable instruments. Filter by `providerId`, and sort with `sortBy` (`volume24h`, `markPrice` or `priceChangePercent24h`) and `order` (`asc` / `desc`).

```bash theme={null}
# Hyperliquid markets, most-traded first
curl --request GET \
  --url 'https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-perps/markets?providerId=hyperliquid&sortBy=volume24h&order=desc' \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]'
```

Each market carries the fields you need to render a trading UI: `baseAsset` / `quoteAsset`, `leverageRange` (`[min, max]`), `supportedMarginModes` (`isolated` / `cross`), `markPrice`, `oraclePrice`, `priceChangePercent24h`, `fundingRate` with `fundingRateIntervalHours`, `makerFee` / `takerFee`, `openInterest` and `minSize`. Treat market ids as opaque values returned by `GET /markets` (for example `hyperliquid-eth-usdc`); do not build them yourself. Use `GET /markets/{marketId}` for one market.

For a price chart, `GET /markets/{marketId}/candles` returns OHLCV candles. It requires an `interval` (for example `1h`) and a `from` timestamp (unix milliseconds), with an optional `to`:

```bash theme={null}
curl --request GET \
  --url 'https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-perps/markets/hyperliquid-eth-usdc/candles?interval=1h&from=1704067200000' \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]'
```

## Funding a trading account and approving the venue

A perps venue holds collateral in a **trading account** that is separate from the user's on-chain wallet balance. Before a user can open a position, you fund that account and complete any one-time approvals the venue requires. Both are `POST /actions` actions that follow the same build → sign → submit flow as any other action; which approvals a venue needs is declared in its `supportedActions` from `GET /providers`.

### Fund the account

The `fund` action moves collateral into the trading account. `fundingMethod` selects how the venue routes the deposit — the values a venue accepts come from its `argumentSchemas`; the example below uses `bridge2` (bridging USDC from Arbitrum), and `lifi` routes from another token or chain. `args.fromToken.network` is a real chain, so it uses CAIP-2.

```bash theme={null}
curl --request POST \
  --url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-perps/actions \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{
  "providerId": "hyperliquid",
  "address": "0xYourAddress",
  "action": "fund",
  "args": {
    "amount": "100",
    "fromToken": {
      "network": "eip155:42161",
      "address": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
    },
    "fundingMethod": "bridge2"
  }
}'
```

A `fund` action returns an on-chain `EVM_TRANSACTION` (its `network` is CAIP-2). Sign it with the [EVM transaction flow](#signing-evm-transactions) below.

<Note>
  A `fund` action reaches `SUCCESS` when the source-chain transaction confirms — **not** when the collateral lands on the venue. The bridge leg settles afterward, so the deposit can credit minutes later. Poll [`POST /balances`](#checking-positions-orders-and-balances) until `availableBalance` reflects the deposit before you show a funded state. Indicative latencies: Arbitrum USDC via `bridge2` under a minute; Ethereum via `lifi` seconds; Base, Polygon, Avalanche, Optimism and Monad via `lifi` about 20 minutes. These are indicative, not guarantees.
</Note>

### Complete venue approvals

A venue declares any one-time approvals it needs in its `supportedActions`. Hyperliquid, for example, places orders through an **agent wallet** that the user authorizes once with `approveAgent`, and may require a one-time `approveBuilderFee`. Build whichever approval actions the venue you are integrating lists, using the `args` from its `argumentSchemas`.

```bash theme={null}
curl --request POST \
  --url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-perps/actions \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{
  "providerId": "hyperliquid",
  "address": "0xYourAddress",
  "action": "approveAgent",
  "args": { "agentName": "my-app" }
}'
```

<Note>
  Funding and venue approvals are one-time prerequisites, not part of every trade. Once the account is funded and any required approvals complete, subsequent `open` / `close` actions do not repeat them. Read the account's collateral back at any time with [`POST /balances`](#checking-positions-orders-and-balances).
</Note>

### Funding sources and limits

Funding, withdrawals and order sizes route through the venue, so their supported chains and minimums are the venue's, not Portal's. On Hyperliquid:

* **Fund sources are EVM chains only.** USDC on Arbitrum funds via `bridge2`; other EVM chains and native tokens route via `lifi`. Solana and Tron are **not** supported fund sources — Hyperliquid has no USDC deposit route from them, so the Yield.xyz Perps API rejects a `fund` from either with `400 EXECUTE_INVALID_ARGUMENT`.
* **Withdrawals return USDC on Arbitrum only**, to the signing address, with a flat \$1 fee and a 2 USDC minimum.
* **`bridge2` deposits below 5 USDC are not credited and are lost.** Enforce the 5 USDC floor before you build a `fund` action.
* **Orders have a \$10 minimum notional**; a smaller `open` is rejected by the venue.

These are Hyperliquid's current limits — confirm them against [Hyperliquid's docs](https://hyperliquid.gitbook.io/hyperliquid-docs/trading/bridge2), and read a venue's own constraints from `GET /providers` rather than hard-coding them.

## Opening a position

Opening a position uses `POST /actions` with `"action": "open"`. You'll then sign each transaction it returns and submit it back.

### Step 1: Create the open action

```bash theme={null}
curl --request POST \
  --url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-perps/actions \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{
  "providerId": "hyperliquid",
  "address": "0xYourAddress",
  "action": "open",
  "args": {
    "marketId": "hyperliquid-eth-usdc",
    "side": "long",
    "size": "1000",
    "leverage": 10,
    "marginMode": "isolated"
  }
}'
```

```json theme={null}
// Example response (trimmed)
{
  "data": {
    "id": "550e8400-...",
    "providerId": "hyperliquid",
    "action": "open",
    "status": "CREATED",
    "summary": {
      "type": "Open Position",
      "direction": "long",
      "size": "1000",
      "leverage": 10,
      "collateral": "100.00",
      "fee": "0.0005",
      "marginMode": "isolated",
      "estimatedLiquidationPrice": 3200
    },
    "transactions": [
      {
        "id": "73729c4d-...",
        "network": "hyperliquid",
        "chainId": "1337",
        "type": "OPEN_POSITION",
        "status": "CREATED",
        "address": "0xYourAddress",
        "signingFormat": "EIP712_TYPED_DATA",
        "signablePayload": {
          "domain": { "name": "Exchange", "version": "1", "chainId": 1337 },
          "primaryType": "Agent",
          "message": { "source": "a", "connectionId": "0xabc123" }
        },
        "rawPayload": "{\"action\":{\"type\":\"order\"},\"nonce\":1756207800000}"
      }
    ],
    "createdAt": "2026-08-26T10:30:00.000Z",
    "completedAt": null
  }
}
```

<Note>
  Take note of `data.id` (the action id) and each transaction's `id`, and show `summary` (`direction`, `size`, `leverage`, `collateral`, `estimatedLiquidationPrice`) to the user before they sign. An action can contain several transactions, which you sign and submit **in order**. Perps adds **no** trading guardrails, so any confirmation or liquidation warning is your UI's responsibility.
</Note>

### Step 2: Sign the transaction

How you sign a transaction is dictated by its `signingFormat`, not by the venue — always sign by the format the API returns on the transaction. Hyperliquid, for example, returns `EIP712_TYPED_DATA` for orders and `EVM_TRANSACTION` for on-chain legs (funding, withdrawals, some approvals). See [Signing by format](#signing-by-format) for the full mapping.

#### Signing EIP-712 typed data

An `EIP712_TYPED_DATA` transaction is signed off-chain, not broadcast on-chain. It carries:

* `signablePayload` — the EIP-712 typed-data structure (`domain`, `primaryType`, `message`) to hash and sign
* `rawPayload` — the venue order the signature authorizes
* `chainId` — the EIP-712 domain chain id, kept exactly as returned

To sign:

1. **Compute the EIP-712 digest** of `signablePayload` using any standard EIP-712 implementation. Portal returns `signablePayload` and `rawPayload` byte-for-byte, so you can independently recompute the venue's `connectionId` from them and verify the order before signing.

2. **Raw-sign the digest** with the Enclave MPC API. `POST /v1/raw/sign/SECP256K1` signs a raw hex digest (without the leading `0x`) and returns the signature.

   ```bash theme={null}
   curl --request POST \
     --url https://mpc-client.portalhq.io/v1/raw/sign/SECP256K1 \
     --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
     --header 'Content-Type: application/json' \
     --data '{
     "share": "[share]",
     "params": "[eip712DigestHexWithout0x]"
   }'
   ```

   The response is `{ "data": "[signatureHexWithout0x]" }`.

3. **Submit the signature** with [Step 3](#step-3-submit-the-signed-transaction), as `signedPayload`. Yield.xyz combines it with the order and forwards it to the venue.

<Tip>
  If you do not need to independently recompute the `connectionId`, `POST /v1/sign` with method `eth_signTypedData_v4` computes the digest for you from the typed-data structure and returns the signature in one call. Raw signing is the canonical path because it preserves that verification step.
</Tip>

#### Signing EVM transactions

An `EVM_TRANSACTION` (funding, withdrawal, on-chain approval) works like any Ethereum transaction. `signablePayload` is a JSON string of the unsigned transaction; parse it and pass the fields to the Enclave MPC API `eth_sendTransaction` method, which signs **and** broadcasts, returning the transaction hash.

```bash theme={null}
curl --request POST \
  --url https://mpc-client.portalhq.io/v1/sign \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{
  "share": "[share]",
  "method": "eth_sendTransaction",
  "params": { "from": "0xYourAddress", "to": "0x...", "data": "0x...", "value": "0x0" },
  "rpcUrl": "https://api.portalhq.io/rpc/v1/eip155/42161",
  "chainId": "eip155:42161"
}'
```

### Step 3: Submit the signed transaction

Report the result to Yield.xyz with `POST /transactions/{transactionId}/submit`. Submit the `signedPayload` (for EIP-712 orders and for transactions you signed but did not broadcast), or the `transactionHash` (for `EVM_TRANSACTION` legs you broadcast with `eth_sendTransaction`). A `signedPayload` submission **must** include `actionId` (the `data.id` from Step 1); a `transactionHash` submission does not. For an EIP-712 order, Portal uses it to verify the signature recovers to the account the action was built for before forwarding, and rejects a mismatched (`PERPS_SIGNATURE_ADDRESS_MISMATCH`), unrecoverable (`PERPS_SIGNATURE_INVALID`), or unhashable (`PERPS_SIGNATURE_UNVERIFIABLE`) signature instead of letting the venue silently strand it.

```bash theme={null}
# EIP-712 order: submit the signature (with actionId for signature verification)
curl --request POST \
  --url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-perps/transactions/[transactionId]/submit \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{ "signedPayload": "0x[signature]", "actionId": "[actionId]" }'

# On-chain leg: submit the broadcast hash
curl --request POST \
  --url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-perps/transactions/[transactionId]/submit \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{ "transactionHash": "0x..." }'
```

The response includes the transaction `status`, an explorer `link`, and — on some venues — a `details` object with venue-specific fill information.

### Step 4: Track the action

Sign and submit every transaction in the action's `transactions` array, in order, waiting for each to confirm. There is no separate step endpoint: poll `GET /actions/{id}` to watch progress and to pick up any further transactions the venue adds. A `status` of `WAITING_FOR_NEXT` means the action is waiting on a submitted transaction before it can continue; the action is complete when `status` is `SUCCESS`.

```bash theme={null}
curl --request GET \
  --url 'https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-perps/actions/[actionId]' \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]'
```

## Checking positions, orders and balances

Read a user's portfolio with the three `POST` endpoints. Each takes a body with an `address` and at least one of `providerId` or `providerIds` (`balances` accepts a single venue only).

```bash theme={null}
# Open positions
curl --request POST \
  --url 'https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-perps/positions' \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{ "providerId": "hyperliquid", "address": "0xYourAddress" }'
```

```json theme={null}
// Example positions response (trimmed)
{
  "data": [
    {
      "marketId": "hyperliquid-eth-usdc",
      "side": "long",
      "size": "0.215",
      "entryPrice": 4000,
      "markPrice": 4025,
      "leverage": 20,
      "marginMode": "isolated",
      "margin": 43,
      "unrealizedPnl": 5.38,
      "funding": -1.24,
      "liquidationPrice": 3810,
      "pendingActions": [
        { "type": "close", "label": "Close Position", "args": { "marketId": "hyperliquid-eth-usdc" } }
      ]
    }
  ]
}
```

`POST /orders` returns resting limit and trigger orders; `POST /balances` returns the trading account's `accountValue`, `usedMargin`, `availableBalance` and `unrealizedPnl`. Each position and order lists `pendingActions` — the actions currently available for it, with pre-filled `args` you can pass straight to `POST /actions`.

## Managing a position

Every management action follows the same build → sign → submit → track flow as `open`. The core walkthrough above applies unchanged; only `action` and `args` differ. The exact `args` per action are described by each venue's `argumentSchemas` from `GET /providers/{providerId}`.

| Action              | What it does                                        | Key `args`                                     |
| ------------------- | --------------------------------------------------- | ---------------------------------------------- |
| `setTpAndSl`        | Set or update stop-loss and take-profit together    | `marketId`, `stopLossPrice`, `takeProfitPrice` |
| `stopLoss`          | Set or update a stop-loss                           | `marketId`, `stopLossPrice`                    |
| `takeProfit`        | Set or update a take-profit                         | `marketId`, `takeProfitPrice`                  |
| `updateLeverage`    | Change a position's leverage                        | `marketId`, `leverage`                         |
| `updateMargin`      | Add or remove margin on an isolated position        | `marketId`, `amount`                           |
| `editOrder`         | Adjust a resting order's price or size in place     | `orderId`, `limitPrice`, `size`                |
| `cancelOrder`       | Cancel one or more resting orders                   | `orderId` or `orderIds`                        |
| `setUnifiedAccount` | Enable/disable unified-account mode where supported | `enabled`                                      |

```bash theme={null}
# Attach a stop-loss and take-profit to an open position
curl --request POST \
  --url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-perps/actions \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{
  "providerId": "hyperliquid",
  "address": "0xYourAddress",
  "action": "setTpAndSl",
  "args": {
    "marketId": "hyperliquid-eth-usdc",
    "stopLossPrice": 3600,
    "takeProfitPrice": 4400
  }
}'
```

## Closing a position and withdrawing

Close a position with `"action": "close"`, then withdraw collateral from the trading account with `"action": "withdraw"`. Both follow the same sign → submit → track flow.

```bash theme={null}
# Close the ETH-USDC position
curl --request POST \
  --url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-perps/actions \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{
  "providerId": "hyperliquid",
  "address": "0xYourAddress",
  "action": "close",
  "args": { "marketId": "hyperliquid-eth-usdc" }
}'

# Withdraw collateral from the trading account
curl --request POST \
  --url https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-perps/actions \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]' \
  --header 'Content-Type: application/json' \
  --data '{
  "providerId": "hyperliquid",
  "address": "0xYourAddress",
  "action": "withdraw",
  "args": { "amount": "100" }
}'
```

## Activity and events

List a user's past actions with `GET /actions?address=0xYourAddress` (filter by `providerId`, `marketId`, `type` or `status`).

For venue-side outcomes that are not actions your user initiated — order fills, liquidations, stop-loss / take-profit triggers — use the events feed:

```bash theme={null}
# Recent events for an address
curl --request GET \
  --url 'https://api.portalhq.io/api/v3/clients/me/integrations/yield-xyz-perps/events?address=0xYourAddress&providerId=hyperliquid' \
  --header 'Authorization: Bearer [clientApiKey|clientSessionToken]'
```

Each event carries an `eventType` (`order_filled`, `liquidation`, `stop_loss_triggered`, `take_profit_triggered`), an `occurredAt` timestamp and the `order` it concerns. Filter with `eventType(s)`, `marketId`, `perpActionId` or `fromDate` / `toDate`. `GET /activity` returns a single unified feed interleaving your user's actions and these events, newest first — convenient for a combined trade-history view.

## Transaction processing

A perps action can require one or more transactions, and different venues sign in different formats. Sign each transaction by its `signingFormat`:

### Signing by format

| `signingFormat`      | How to sign                                                                                            | What to submit                  |
| -------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------- |
| `EIP712_TYPED_DATA`  | Compute the EIP-712 digest of `signablePayload`, then `POST /v1/raw/sign/SECP256K1`                    | `signedPayload` (the signature) |
| `EVM_TRANSACTION`    | Parse the `signablePayload` JSON, then `POST /v1/sign` with `eth_sendTransaction` (signs + broadcasts) | `transactionHash`               |
| `SOLANA_TRANSACTION` | `POST /v1/sign` with `sol_signAndSendTransaction`                                                      | `transactionHash`               |
| `COSMOS_TRANSACTION` | Sign the payload for the venue's chain                                                                 | `signedPayload`                 |

`EIP712_TYPED_DATA` and `EVM_TRANSACTION` cover Hyperliquid (orders and on-chain funding legs respectively). The other formats appear only on venues that use those chains; the principle is the same — sign by the declared format and submit the signature or the broadcast hash.

## Handling errors

Yield.xyz Perps errors are returned as Portal errors:

* `400`: invalid request (the message names the field), an unsupported chain id, a precondition the venue rejected (for example insufficient margin), a request Yield.xyz rejected (its message is passed through), or a Yield.xyz API key that is missing or was rejected. When the venue returns a machine-readable code, Portal surfaces it as `details.code`
* `404`: unknown market, venue, action, event or transaction id
* `429`: Yield.xyz rate limit hit; back off and retry
* `503`: Yield.xyz is unreachable or failed upstream
* `500` with `id: INTEGRATION_RESPONSE_SCHEMA_DRIFT`: Yield.xyz changed a response shape and Portal did not forward it. Treat it as a temporary outage of that feature; see [Error codes](/resources/error-codes)

Response enumerations (action, order, transaction and event types and statuses) may gain values over time; treat values you do not recognize as opaque rather than failing.

## Best practices

1. **Show the `summary`** (`direction`, `size`, `leverage`, `collateral`, `estimatedLiquidationPrice`) before the user signs — Portal adds no trading guardrails
2. **Fund and approve first**: a position cannot open until the trading account has collateral and any venue-required approvals are complete (on Hyperliquid, the agent wallet)
3. **Sign each transaction by its `signingFormat`** and submit the signature or broadcast hash it expects
4. **Process transactions sequentially** and poll `GET /actions/{id}` until the action reaches `SUCCESS`
5. **Verify EIP-712 orders** by recomputing the venue `connectionId` from the byte-for-byte `signablePayload` before signing
6. **Handle `INTEGRATION_RESPONSE_SCHEMA_DRIFT`** as a feature outage rather than a user error
7. **Keep gas on the wallet** for the on-chain funding and withdrawal legs

## Supported venues

Perps launches on Hyperliquid; the exact list of live venues is returned by `GET /providers`. Use the `providerId` values that endpoint returns rather than a fixed list — a venue Yield.xyz adds later needs no code change on your side. On-chain funding and withdrawal legs settle on real chains (for example Arbitrum, `eip155:42161`), addressed in CAIP-2.

## Next Steps

* Set up the integration: [Yield.xyz Perps](/integrations/Yield/yield-xyz-perps)
* Browse the [Yield.xyz Perps API reference](/api-reference/yieldxyz-perps/list-trading-venues)
* Learn about [signing Ethereum transactions](./sign-ethereum-transactions)
* Review the [account-abstraction](/resources/account-abstraction) requirement — perps require a non-AA (`isAccountAbstracted: false`) client
