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

# Bridge Quote

> [Alpha Preview] Get a cross-chain bridge quote with a ready-to-sign deposit transaction. EVM, Solana, and HyperLiquid.

<Warning>
  **Alpha Preview** — Endpoints, response shape, contract addresses, and supported
  routes may change without notice. Don't depend on it for production-critical
  flows until it leaves alpha.
</Warning>

`GET /api/2/bridge/quote` returns a ready-to-sign deposit transaction plus a
`intentId` you'll use to poll status. The Mobula solver detects the deposit
(flash blocks on Base, gRPC on Solana) and fills on the destination chain.

Typical end-to-end latency: \~500 ms for Base ↔ Solana, \~1–3 s elsewhere.

## Query parameters

| Name                 | Required          | Notes                                                                                                                                                                                                                                                                                                |
| -------------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `apiKey`             | yes               | Your Mobula API key, passed **in the query string** (`?apiKey=…`). `/quote` reads it from the query, not an `Authorization` header — omitting it returns `{ "error": "Missing required parameter: apiKey" }`.                                                                                        |
| `originChainId`      | yes               | One of the supported chain IDs (see [Bridge Routes](/rest-api-reference/endpoint/bridge-routes)).                                                                                                                                                                                                    |
| `destinationChainId` | yes               | Same set. When equal to `originChainId`, the endpoint short-circuits to the Swap API — see [Same-chain quotes](#same-chain-quotes).                                                                                                                                                                  |
| `walletAddress`      | yes               | **Destination recipient.** Format-validated against the destination chain: EVM regex for `evm:*` and `hl:mainnet`, Base58 for `solana:solana`.                                                                                                                                                       |
| `amount`             | yes (cross-chain) | Decimal human units (`"0.05"`, not wei). Must be finite, positive, ≤ `1e15`. Not required when source and destination are the same chain.                                                                                                                                                            |
| `originToken`        | no                | Omit, or pass `0x0000…0000` / `0xeeee…eeee` for the native token. EVM addresses are checksummed server-side.                                                                                                                                                                                         |
| `destinationToken`   | no                | Same rules. When omitted on a Solana destination, the API substitutes wSOL (`So11111111111111111111111111111111111111112`).                                                                                                                                                                          |
| `senderAddress`      | conditional       | **Required** for Solana SPL bridges (the server needs it to build the ATA + SPL transfer + memo). For HL origin, this is the HL spot wallet that will sign — it must equal the EIP-712 signer (see [Signed-quote flow](#signed-quote-flow)). Optional for EVM origins (defaults to `walletAddress`). |
| `feePayerAddress`    | no                | Solana origin only: the Solana address that pays the deposit transaction's fee (set as the built transaction's fee payer). Defaults to `senderAddress`. Must be a valid Solana address or the quote returns `"feePayerAddress must be a Solana address"`.                                            |
| `slippage`           | no                | Percent. Default `1`, valid range `0` to `50`.                                                                                                                                                                                                                                                       |
| `destinationType`    | no                | HyperLiquid destinations only: which venue the funds land in — `spot` (default) or `perps`. Ignored on non-HL destinations. Invalid values return `"Invalid destinationType: must be 'spot' or 'perps'"`.                                                                                            |
| `originType`         | no                | HyperLiquid origins only: which venue the deposit is pulled from — `spot` (default) or `perps`. Ignored on non-HL origins. Invalid values return `"Invalid originType: must be 'spot' or 'perps'"`.                                                                                                  |
| `signature`          | conditional       | EIP-712 signature over the typed-data payload returned by the unsigned call. **Required** for `evm:*` and `hl:mainnet` origins to commit the prediction. Omit on the first call to preview the quote + receive the typedData to sign. See [Signed-quote flow](#signed-quote-flow).                   |
| `intentId`           | conditional       | Echo back the `intentId` returned by the unsigned call when submitting `signature`. Format `xxxxxxx-xxxxxxx-xxx` (lowercase hex).                                                                                                                                                                    |
| `deadline`           | conditional       | Echo back the `deadline` returned by the unsigned call. Unix seconds. Server rejects expired deadlines.                                                                                                                                                                                              |
| `minAmountOut`       | conditional       | Echo back the `minAmountOut` (raw destination-token units) from the typedData. The signed value is authoritative — the server reconstructs the typedData from this exact value before verifying the signature.                                                                                       |

Validation errors come back as `{ "error": "..." }` with HTTP 200 (or HTTP 400
for invalid signatures) — always check the `error` key before reading `data`.

## Response

```json theme={null}
{
  "data": {
    "intentId": "a3b4ba1-e34523c-324",
    "deadline": 1764032100,
    "typedData": { /* EIP-712 payload to sign — see Signed-quote flow */ },
    "signatureRequired": true,
    "prediction": { "persisted": false },
    "estimatedAmountOut": "0.68421052",
    "estimatedAmountOutUsd": "1.99",
    "recommendedSlippage": 1.5,
    "fees": {
      "bridgeFeeBps": 5,
      "bridgeFeeUsd": "0.0010",
      "destFillGasUsd": "0.0800",
      "gasFeeUsd": "0.0800",
      "totalFeeUsd": "0.0810",
      "destActivationCostUsd": "0.0020"
    },
    "estimatedTimeMs": 1000,
    "maxTradeUsd": 400,
    "destinationType": "spot",
    "originType": "spot",
    "steps": [ /* optional, see below */ ],
    "deposit": { /* one of evm | solana | hl */ }
  }
}
```

* `intentId` is the user-facing handle, format `xxxxxxx-xxxxxxx-xxx` (lowercase
  hex). Pass it to `GET /status/:id` or `/status/:id/wait`. There is also an
  on-chain `bytes32` intent ID emitted by `MobulaBridge` on EVM deposits — both
  resolve in `/status/:id`, so use whichever you have. **You must echo this exact
  `intentId` back via the `intentId` query param when submitting the signature**
  — the signed payload binds to it.
* `deadline` is Unix seconds. The server rejects signed calls past this point.
* `typedData` is the EIP-712 structured-data payload your wallet should sign
  (see [Signed-quote flow](#signed-quote-flow) for the full schema).
* `signatureRequired: true` for `evm:*` and `hl:mainnet` origins. `false` for
  `solana:solana` (the depositor-signed memo replaces the signature).
* `prediction.persisted` indicates whether the server has committed your signed
  intent. `false` on the unsigned preview call; `true` after a successful signed
  call.
* `steps` is present only when the deposit needs more than one transaction.
  Today that means EVM ERC-20 origins: `[approve, bridgeToken | swapAndBridge]`.
  Native EVM bridges and Solana/HL bridges omit `steps`.
* `recommendedSlippage` is the slippage % we suggest signing with — the route's
  implied spread (`(1 − outUsd/inUsd)×100`) plus a `0.5%` drift buffer, rounded
  up to `0.1`, floored at `1`, and capped at `50` (`null` when USD prices are
  unavailable). The solver refunds any fill below the signed `minAmountOut`
  (failure code `slippage`), so a tolerance under this value is a near-guaranteed
  refund. If your `slippage` is below it, re-quote at the recommendation before
  signing.
* `fees` are **real, deducted** amounts — there is no placeholder. `bridgeFeeUsd`
  is the Mobula protocol fee (`bridgeFeeBps`, currently `5`); `destFillGasUsd` is
  what the solver pays to fill on the destination chain; `gasFeeUsd` equals
  `destFillGasUsd`. `destActivationCostUsd` appears **only** when the destination
  needs a one-off account-creation cost (e.g. Solana ATA rent for a first-time
  recipient) — it's omitted otherwise. `totalFeeUsd` is the sum of all present
  fee fields. `estimatedAmountOut` / `estimatedAmountOutUsd` are already net of
  all of it; the user additionally pays only origin-chain gas to broadcast the
  deposit.
* `destinationType` / `originType` are echoed back only for HyperLiquid routes
  (`spot` or `perps`), reflecting the venue the funds land in / are pulled from.
* `maxTradeUsd` is `$400`. Amounts above that return
  `"Amount $X exceeds maximum trade of $400"`.

## `deposit` shapes

The shape depends on `originChainId`. Sign and broadcast whichever one is
present.

### EVM origin (`deposit.evm`)

```json theme={null}
{
  "to": "0xa834E70303322D86E5DaE95ee47E9c6a073d9812",
  "data": "0x...",
  "value": "50000000000000000",
  "chainId": 8453,
  "approvalAddress": "0x...",      // present for ERC-20 origins
  "approvalToken": "0x...",        // present for ERC-20 origins
  "approvalAmount": "115792...255" // MAX_UINT256
}
```

Three code paths:

* **Native ETH/BNB/POL** — single `bridge()` call on `MobulaBridge`. `value`
  is the raw amount in wei. No `steps`.
* **Direct-bridge tokens** — `approve` step to `MobulaBridge`, then
  `bridgeToken()`. `value` is `"0"`. The set is USDC on all four chains, plus
  Base's bridged USDbC and USDT on Arbitrum and Polygon (BSC is USDC-only).
* **Any other ERC-20** — `approve` step to `SwapBridgeHelper`, then
  `swapAndBridge()` — atomic swap to native + bridge in one TX. The embedded
  swap calldata is validated server-side to start with the
  `MobulaRouter.executeRoute` selector (`0xa564dfa4`); if it doesn't, the
  quote returns `"Swap quote failed: invalid calldata selector"`.

`MobulaBridge` (MobulaBridgeV2, deployed 2026-06-04) is the **same proxy address
on every EVM chain**:

| Chain                  | Bridge contract                              |
| ---------------------- | -------------------------------------------- |
| `evm:8453` (Base)      | `0xa834E70303322D86E5DaE95ee47E9c6a073d9812` |
| `evm:56` (BSC)         | `0xa834E70303322D86E5DaE95ee47E9c6a073d9812` |
| `evm:42161` (Arbitrum) | `0xa834E70303322D86E5DaE95ee47E9c6a073d9812` |
| `evm:137` (Polygon)    | `0xa834E70303322D86E5DaE95ee47E9c6a073d9812` |

The swap-and-bridge path approves a separate per-chain `SwapBridgeHelper` (the
spender named in the `approve` step) — always approve the spender the step
specifies, not a hardcoded address.

Approval handling: `approvalAmount` is always `MAX_UINT256`, so a single
approve per (token, spender) is enough forever. Skip the `approve` step only
if the current on-chain allowance already covers `amount`.

### Solana origin (`deposit.solana`)

Two shapes depending on token:

* **Native SOL** — `{ to, amount, memo }`. Build a `SystemProgram.transfer`
  for `amount` lamports to `to` (the solver address), then add a memo
  instruction (program `MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr`) whose
  data is the `memo` string. The memo is a JSON blob the solver
  parses to recover `intentId`, `destinationChainId`, `recipient`,
  `destinationToken`, and `minAmountOut`.
* **SPL** — `{ type: "spl-transfer", serializedTx }`. The server has
  already built the full versioned transaction (SPL transfer + ATA creation
  if missing + memo). Just `VersionedTransaction.deserialize`, sign, and
  send.

### HyperLiquid origin (`deposit.hl`)

```json theme={null}
{
  "type": "usdSend",
  "to": "0x74CfC17edF89aD6134c04c446c3Be6dD288F0B8d",
  "amount": "1.0"
}
```

Submit this action (USDC) to the solver L1 address using your HL signer.

## Same-chain quotes

When `originChainId === destinationChainId`, the server short-circuits
into a swap-wrapper. The response is the **raw Swap API response**, not the
bridge shape above (no `intentId`, no `deposit.evm/solana/hl`). Approval
amounts in the response are overridden to `MAX_UINT256` server-side.

Branch on the response: `data.deposit` present → bridge flow; otherwise →
swap flow.

## Signed-quote flow

For `evm:*` and `hl:mainnet` origins the destination token (and, for HL, the
destination address) is not committed on chain — the server holds it against
the depositor's address until the deposit lands. Without binding that to the
depositor's key, anyone who knows the address could overwrite it and redirect
funds to a different token. To close that hole, `/quote` enforces an EIP-712
signature flow.

The flow is two API calls plus one wallet signature:

1. **Preview call** — `GET /quote?...` with no `signature`. Server returns the
   quote, the deposit calldata, and a `typedData` payload. **Nothing is
   committed yet.**
2. **Sign** — your wallet signs `typedData` (e.g. `eth_signTypedData_v4` for
   injected wallets, `walletClient.signTypedData` with viem). The signer's
   address must equal `typedData.message.sender`.
3. **Commit call** — `GET /quote?...&signature=<sig>&intentId=<id>&deadline=<ts>&minAmountOut=<raw>`
   with the same input params as call 1. Server reconstructs the typedData
   from the query params, recovers the signer, and commits your signed intent
   if everything lines up. Returns the same response shape with
   `prediction.persisted: true`.
4. **Broadcast** — submit `deposit.evm` (or `deposit.hl`) on chain.

### EIP-712 schema

```
Domain:
  name:    "Mobula Bridge"
  version: "1"
  chainId: <numeric origin chain id>   // 8453, 56, 42161, 137 — and 1 (NOT 999) for hl:mainnet

BridgeIntent:
  intentId           string    — same as `data.intentId` (dashed hex, signed as a string)
  sender             address   — depositor EVM key (HL origin: HL spot wallet; EVM: walletAddress)
  originChainId      string    — e.g. "evm:8453"
  originToken        string    — "0x000…0" for native, or token address / HL token id
  amountIn           uint256   — raw origin-token units
  destinationChainId string
  destinationToken   string
  recipient          bytes32   — EVM dest: address left-padded; Solana dest: bs58-decoded
  minAmountOut       uint256   — raw destination-token units, echoed back as the `minAmountOut` query param
  deadline           uint64    — Unix seconds, echoed back as the `deadline` query param
```

viem omits the `EIP712Domain` type from `types` — inject it client-side
(`name:string, version:string, chainId:uint256`) before signing if your signer
needs it.

**HyperLiquid specifics.** HL signs all actions under Ethereum mainnet, so for
`hl:mainnet` origins `typedData.domain.chainId` is `1` (not `999`) — switch the
wallet to chain `1` before signing. An HL bridge then needs **two** signatures:
(1) this EIP-712 `BridgeIntent` confirm, then (2) the HL `usdSend` transfer to
the solver.

### Failure modes on the commit call

* `400 Invalid bridge intent signature: ...` — signature did not recover to
  the depositor address. Re-check `typedData.message.sender` and the signer.
* `400 Signature deadline has expired or is invalid` — `deadline` is past
  `now`. Re-quote.
* `400 Signed-mode quote requires intentId, deadline, minAmountOut, and signature` —
  one of the four signed-mode params is missing.

## Side effects

`/quote` commits your signed intent — bound to `(sender, originChainId,
destinationChainId)` — **only when called with a valid signature** (Solana
origin: committed on every call, since the memo carries the binding). The
server uses it to resolve `destinationToken`, `recipient`, and `slippage` when
the deposit lands. For EVM/HL origins a deposit with no committed signature is
rejected (and refunded) — so always complete the commit call before
broadcasting.

## Example

EVM origin (signed-quote flow, Base → BSC, 100 USDC → USDT):

```typescript theme={null}
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { base } from "viem/chains";

const account = privateKeyToAccount("0xYourPrivKey");
const client = createWalletClient({ account, chain: base, transport: http() });

// 1. Preview call (no signature, nothing committed).
const baseParams = new URLSearchParams({
  originChainId: "evm:8453",
  destinationChainId: "evm:56",
  originToken: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913", // USDC on Base
  destinationToken: "0x55d398326f99059fF775485246999027B3197955", // USDT on BSC
  amount: "100",
  walletAddress: account.address,
  senderAddress: account.address,
  apiKey: "YOUR_API_KEY",
});

const preview = await fetch(`https://api.mobula.io/api/2/bridge/quote?${baseParams}`)
  .then((r) => r.json());
if (preview.error) throw new Error(preview.error);
const { intentId, deadline, typedData, estimatedAmountOut } = preview.data;

// 2. Sign the typed data.
const signature = await client.signTypedData({
  account,
  domain: typedData.domain,
  types: typedData.types,
  primaryType: typedData.primaryType,
  message: typedData.message,
});

// 3. Commit call (server verifies + commits your signed intent).
const commitParams = new URLSearchParams(baseParams);
commitParams.set("intentId", intentId);
commitParams.set("deadline", String(deadline));
commitParams.set("minAmountOut", typedData.message.minAmountOut);
commitParams.set("signature", signature);

const committed = await fetch(`https://api.mobula.io/api/2/bridge/quote?${commitParams}`)
  .then((r) => r.json());
if (committed.error) throw new Error(committed.error);

// 4. Broadcast the on-chain deposit.
const tx = committed.data.deposit.evm; // approve+bridgeToken steps in committed.data.steps
const hash = await client.sendTransaction({
  to: tx.to,
  data: tx.data,
  value: BigInt(tx.value),
});
console.log("Deposit tx:", hash);
console.log("Poll status with:", intentId);
```

For a full sign-and-broadcast walkthrough across EVM, Solana, and HyperLiquid
origins, see the [Bridge Implementation guide](/guides/bridge-implementation).
After broadcasting the deposit, poll
[`/status/:id/wait`](/rest-api-reference/endpoint/bridge-status) with
`quote.intentId`.


## OpenAPI

````yaml get /2/bridge/quote
openapi: 3.0.0
info:
  version: 1.0.0
  title: Mobula API
  description: >-
    Documentation of the Mobula API


    **Demo API**: The default server (demo-api.mobula.io) is a demo API with
    rate limits.

    For production use, please use api.mobula.io with an API key from
    https://admin.mobula.io
servers:
  - url: https://demo-api.mobula.io/api/
    description: Demo API (rate limited, for testing only)
  - url: https://api.mobula.io/api/
    description: Production API (requires API key)
security: []
tags:
  - name: V2 - Token
    description: Token details, price, security, ATH, and holder data
  - name: V2 - Market Data
    description: Market details, OHLCV history, and lighthouse metrics
  - name: V2 - Trades
    description: Token trades, enriched trades, and trade filters
  - name: V2 - Wallet
    description: Wallet positions, activity, trades, analysis, and labels
  - name: V2 - Assets
    description: Cross-chain asset details and price history
  - name: V2 - Swap
    description: Swap quoting and execution
  - name: V2 - Perps
    description: Perpetual futures quoting, execution, and positions
  - name: V2 - Bridge
    description: Cross-chain bridge quoting and intent status (Alpha Preview)
  - name: V2 - DeFi
    description: Bonding pools and pulse data
  - name: V2 - Search
    description: Universal fast search
  - name: V2 - Blockchains
    description: System metadata and chain listings
  - name: V1 - Market Data
    description: Market prices, history, sparklines, pairs, and multi-data
  - name: V1 - Wallet
    description: Wallet portfolio, transactions, history, and NFTs
  - name: V1 - Token
    description: First buyers
  - name: V1 - Trades
    description: Market trades by pair
  - name: V1 - Metadata
    description: Token metadata, categories, trendings, and news
  - name: V1 - Assets
    description: List all assets
  - name: V1 - Search
    description: Search for assets, tokens, and pairs
  - name: V1 - DeFi
    description: Bonding pool pulse data
  - name: V1 - Blockchains
    description: Blockchain listings, pairs, and stats
  - name: V1 - Webhooks
    description: Webhook management
  - name: V1 - Feed
    description: Custom feed creation
paths:
  /2/bridge/quote:
    get:
      tags:
        - V2 - Bridge
      summary: Get bridge quote
      description: >-
        [Alpha Preview] Get a cross-chain bridge quote with a ready-to-sign
        deposit transaction. Supported chains: Base (evm:8453), BSC (evm:56),
        Arbitrum (evm:42161), Polygon (evm:137), Solana (solana:solana),
        HyperLiquid (hl:mainnet). For native tokens, omit
        originToken/destinationToken or pass the zero address. ERC-20 origins on
        EVM go through SwapBridgeHelper (atomic swap+bridge); SPL origins on
        Solana require senderAddress. Max trade is $400 USD per transaction.
      parameters:
        - schema:
            type: string
            enum:
              - evm:8453
              - evm:56
              - evm:42161
              - evm:137
              - solana:solana
              - hl:mainnet
            description: Origin chain ID (e.g., "evm:8453", "solana:solana", "hl:mainnet")
          required: true
          description: Origin chain ID (e.g., "evm:8453", "solana:solana", "hl:mainnet")
          name: originChainId
          in: query
        - schema:
            type: string
            enum:
              - evm:8453
              - evm:56
              - evm:42161
              - evm:137
              - solana:solana
              - hl:mainnet
            description: >-
              Destination chain ID (e.g., "evm:8453", "solana:solana",
              "hl:mainnet")
          required: true
          description: >-
            Destination chain ID (e.g., "evm:8453", "solana:solana",
            "hl:mainnet")
          name: destinationChainId
          in: query
        - schema:
            type: string
            description: Human-readable amount of origin token to bridge (e.g., "0.1")
          required: true
          description: Human-readable amount of origin token to bridge (e.g., "0.1")
          name: amount
          in: query
        - schema:
            type: string
            description: >-
              Recipient wallet address on the destination chain (EVM hex, Solana
              base58, or HL hex).
          required: true
          description: >-
            Recipient wallet address on the destination chain (EVM hex, Solana
            base58, or HL hex).
          name: walletAddress
          in: query
        - schema:
            type: string
            description: >-
              Origin token contract/mint address. Omit or pass the zero address
              for the native token.
          required: false
          description: >-
            Origin token contract/mint address. Omit or pass the zero address
            for the native token.
          name: originToken
          in: query
        - schema:
            type: string
            description: >-
              Destination token contract/mint address. Omit or pass the zero
              address for the native token.
          required: false
          description: >-
            Destination token contract/mint address. Omit or pass the zero
            address for the native token.
          name: destinationToken
          in: query
        - schema:
            type: string
            description: 'Slippage tolerance in percent (0-50, default: 1).'
          required: false
          description: 'Slippage tolerance in percent (0-50, default: 1).'
          name: slippage
          in: query
        - schema:
            type: string
            description: >-
              Origin-chain sender address. Required when bridging an SPL token
              from Solana (the wallet signing the swap+deposit TX).
          required: false
          description: >-
            Origin-chain sender address. Required when bridging an SPL token
            from Solana (the wallet signing the swap+deposit TX).
          name: senderAddress
          in: query
        - schema:
            type: string
          required: false
          description: >-
            Solana origin only. Address that pays the deposit transaction fee
            (set as the built transaction's fee payer). Defaults to
            senderAddress.
          name: feePayerAddress
          in: query
        - schema:
            type: string
            enum:
              - spot
              - perps
          required: false
          description: >-
            HyperLiquid destinations only. Which venue the funds land in.
            Default "spot". Ignored on non-HL destinations.
          name: destinationType
          in: query
        - schema:
            type: string
            enum:
              - spot
              - perps
          required: false
          description: >-
            HyperLiquid origins only. Which venue the deposit is pulled from.
            Default "spot". Ignored on non-HL origins.
          name: originType
          in: query
        - schema:
            type: string
          required: false
          description: >-
            Your Mobula API key, passed in the query string. /quote reads it
            from the query, not an Authorization header.
          name: apiKey
          in: query
        - schema:
            type: string
          required: false
          description: >-
            EIP-712 signature over the typedData returned by the unsigned call.
            Required for evm:* and hl:mainnet origins to commit the prediction.
            Omit on the first (preview) call.
          name: signature
          in: query
        - schema:
            type: string
          required: false
          description: >-
            Echo back the intentId returned by the unsigned call when submitting
            signature (signed-quote flow).
          name: intentId
          in: query
        - schema:
            type: string
          required: false
          description: >-
            Echo back the deadline (Unix seconds) returned by the unsigned call.
            Server rejects expired deadlines.
          name: deadline
          in: query
        - schema:
            type: string
          required: false
          description: >-
            Echo back the minAmountOut (raw destination-token units) from the
            typedData. The signed value is authoritative.
          name: minAmountOut
          in: query
      responses:
        '200':
          description: >-
            Bridge quote response. Either `data` is populated with quote +
            deposit instructions, or `error` describes why the quote could not
            be built.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      intentId:
                        type: string
                        description: >-
                          User-facing intent handle (format
                          xxxxxxx-xxxxxxx-xxx). Pass to /status/:id. Echo back
                          via the intentId query param when submitting the
                          signature.
                      deadline:
                        type: number
                        description: >-
                          Unix seconds. The server rejects signed calls past
                          this point. Echo back via the deadline query param.
                      typedData:
                        type: object
                        description: >-
                          EIP-712 structured-data payload to sign (evm:* and
                          hl:mainnet origins). Contains domain, types,
                          primaryType, and message.
                      signatureRequired:
                        type: boolean
                        description: >-
                          true for evm:* and hl:mainnet origins; false for
                          solana:solana (the depositor-signed memo replaces the
                          signature).
                      prediction:
                        type: object
                        properties:
                          persisted:
                            type: boolean
                            description: >-
                              Whether the server has committed your signed
                              intent. false on the unsigned preview call; true
                              after a successful signed call (or any Solana
                              quote).
                      estimatedAmountOut:
                        type: string
                        description: >-
                          Estimated amount of destination token the recipient
                          will receive (8 decimals). Already net of all fees.
                      estimatedAmountOutUsd:
                        type: string
                        description: USD value of the estimated output (2 decimals).
                      recommendedSlippage:
                        type: number
                        nullable: true
                        description: >-
                          Slippage % we suggest signing with (route implied
                          spread + drift buffer, clamped to [1, 50]). null when
                          USD prices are unavailable.
                      fees:
                        type: object
                        properties:
                          bridgeFeeBps:
                            type: number
                            description: Mobula protocol fee in basis points (currently 5).
                          bridgeFeeUsd:
                            type: string
                            description: Mobula protocol fee in USD.
                          destFillGasUsd:
                            type: string
                            description: >-
                              Gas the solver pays to fill on the destination
                              chain, in USD.
                          gasFeeUsd:
                            type: string
                            description: Estimated gas fee in USD. Equals destFillGasUsd.
                          totalFeeUsd:
                            type: string
                            description: Sum of all present fee fields, in USD.
                          destActivationCostUsd:
                            type: string
                            description: >-
                              One-off destination account-creation cost (e.g.
                              Solana ATA rent for a first-time recipient), in
                              USD. Present only when non-zero.
                        required:
                          - bridgeFeeBps
                          - bridgeFeeUsd
                          - destFillGasUsd
                          - gasFeeUsd
                          - totalFeeUsd
                      estimatedTimeMs:
                        type: number
                        description: Estimated end-to-end fill latency in milliseconds.
                      maxTradeUsd:
                        type: number
                        description: Max trade size in USD for this route.
                      destinationType:
                        type: string
                        enum:
                          - spot
                          - perps
                        description: >-
                          Echoed for HyperLiquid routes — the venue the funds
                          land in.
                      originType:
                        type: string
                        enum:
                          - spot
                          - perps
                        description: >-
                          Echoed for HyperLiquid routes — the venue the deposit
                          is pulled from.
                      steps:
                        type: array
                        description: >-
                          Ordered steps the user must execute (e.g., approve →
                          bridge). Present when the deposit requires multiple
                          transactions (EVM ERC-20 origins).
                        items:
                          type: object
                          properties:
                            type:
                              type: string
                              description: >-
                                Step type: "approve", "bridge", "bridgeToken",
                                or "swapAndBridge".
                            description:
                              type: string
                            tx:
                              type: object
                              properties:
                                to:
                                  type: string
                                data:
                                  type: string
                                value:
                                  type: string
                                chainId:
                                  type: number
                                approvalAddress:
                                  type: string
                                approvalToken:
                                  type: string
                                approvalAmount:
                                  type: string
                              required:
                                - to
                                - data
                                - value
                                - chainId
                          required:
                            - type
                            - tx
                      deposit:
                        type: object
                        description: >-
                          Ready-to-sign deposit payload. Exactly one of `evm`,
                          `solana`, or `hl` is populated, matching
                          `originChainId`.
                        properties:
                          evm:
                            type: object
                            properties:
                              to:
                                type: string
                              data:
                                type: string
                              value:
                                type: string
                              chainId:
                                type: number
                              approvalAddress:
                                type: string
                              approvalToken:
                                type: string
                              approvalAmount:
                                type: string
                            required:
                              - to
                              - data
                              - value
                              - chainId
                            description: >-
                              EVM transaction payload (native, direct
                              bridgeToken, or swapAndBridge).
                          solana:
                            type: object
                            properties:
                              type:
                                type: string
                                enum:
                                  - spl-transfer
                                description: >-
                                  Present only on the SPL shape. Native SOL
                                  omits type (to/amount/memo).
                              to:
                                type: string
                              amount:
                                type: string
                                description: Amount in lamports (native SOL shape).
                              memo:
                                type: string
                                description: >-
                                  JSON-encoded memo carrying destination chain,
                                  recipient, destination token, and minAmountOut
                                  (native SOL shape).
                              serializedTx:
                                type: string
                                nullable: true
                                description: >-
                                  Base64-encoded VersionedTransaction (SPL shape
                                  — SPL transfer + ATA creation if missing +
                                  memo, prebuilt).
                            description: >-
                              Solana deposit. Native SOL: memo-based transfer
                              (to/amount/memo). SPL: type=spl-transfer with
                              serializedTx.
                          hl:
                            type: object
                            properties:
                              type:
                                type: string
                                enum:
                                  - usdSend
                                  - spotSend
                              to:
                                type: string
                              amount:
                                type: string
                            required:
                              - type
                              - to
                              - amount
                            description: >-
                              HyperLiquid Core deposit payload (USDC via
                              usdSend).
                    required:
                      - intentId
                      - estimatedAmountOut
                      - fees
                      - estimatedTimeMs
                      - maxTradeUsd
                      - deposit
                  error:
                    type: string
                    description: >-
                      Error message when the quote could not be built (missing
                      params, unsupported route, price unavailable, amount over
                      cap, swap failed, …).

````