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

# Swap

> Quote a route and get back exactly what the user should do next.

```typescript theme={"system"}
import { quoteSwap } from "@hypermid/sdk";

const quote = await quoteSwap(
  {
    srcChain: 8453,
    tokenIn: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    dstChain: 42161,
    tokenOut: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
    amountIn: "25000000",
    recipient: userAddress,
    srcAddress: userAddress,
  },
  { apiKey: publishableKey },   // optional — anonymous works
);
```

Omit `dstChain`, or set it equal to `srcChain`, for a same-chain swap. See the
[swap orchestration guide](/guides/swap) for the whole flow.

## The result forces the branch

```typescript theme={"system"}
interface SwapQuote {
  execute: SwapTransaction | SwapDeposit;   // discriminated on `kind`
  estimatedOut: string;
  minOut: string;
  expiresAt: number;                        // UNIX SECONDS
  via?: { key: string; name: string };
}
```

`execute` is a **discriminated union**, deliberately. Some routes are signed
transactions and some are deposits to an address, and the two are not
interchangeable — treating a deposit route as a transaction produces a
transaction that does nothing. Making it a union means the compiler forces the
branch rather than trusting you to remember:

```typescript theme={"system"}
if (quote.execute.kind === "deposit") {
  show(quote.execute.address, quote.execute.memo);   // memo may be required
} else {
  await sendTransactionAsync({
    to: quote.execute.to,
    data: quote.execute.data,
    value: BigInt(quote.execute.value),
    chainId: Number(quote.execute.chain),
  });
}
```

<Warning>
  On memo chains a transfer sent without the memo may be unrecoverable. Render it
  as prominently as the address.
</Warning>

## Expiry

`expiresAt` is **Unix seconds**, not milliseconds and not a date string:

```typescript theme={"system"}
if (quote.expiresAt <= Date.now() / 1000) {
  quote = await quoteSwap(request, opts);   // re-quote, do not retry
}
```

A stale route reverts on slippage rather than filling at a bad price. That is
the safe failure, but it is still a failed transaction for your user — so
re-quote before submitting if any time has passed.

## Choosing the flow

```typescript theme={"system"}
quoteSwap(request, { prefer: "deposit" });
```

When a route offers both, `prefer` picks. `"transaction"` (the default) suits a
connected wallet; `"deposit"` suits a payer who has not connected one, or who
is funding from an exchange.

## Refunds on intent routes

Intent routes need `refundRecipient` at quote time. An intent is a solver's
promise to deliver, and a failed promise has to unwind somewhere — collect the
address while the user is still there, not at failure time when they are gone.

Aggregator routes do not need it: funds stay in the user's custody until the
swap executes.

## `via` is for display only

```typescript theme={"system"}
<span>Routed via {quote.via?.name}</span>
```

Never branch on it. Routing is chosen per quote and the provider set changes;
code that switches on a provider name breaks silently the first time a better
route wins.
