Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.rhinestone.dev/llms.txt

Use this file to discover all available pages before exploring further.

To get started with Warp, request a quote for a crosschain intent. Use the /quotes endpoint. You’ll need the destination chain, the token and amount on that chain, and the account address:
Get Quote
const baseUrl = "https://v1.orchestrator.rhinestone.dev";
const apiKey = "YOUR_RHINESTONE_API_KEY";

const payload = {
  account: {
    address: EOA_ADDRESS,
    accountType: "EOA",
  },
  destinationChainId: "eip155:8453",
  tokenRequests: [
    {
      tokenAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      amount: "5000000",
    },
  ],
};

const res = await fetch(`${baseUrl}/quotes`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": apiKey,
    "x-api-version": "2026-04.blanc",
  },
  body: JSON.stringify(payload),
});

const { routes } = await res.json();
const route = routes[0];
Chain ids on every field are CAIP-2 strings (eip155:<chainId>).

Understanding the response

The response is { routes }, an array pre-ranked by a cost/speed tradeoff. Pick routes[0] unless you have your own criteria. Each route carries everything you need to sign and submit:
FieldDescription
intentIdServer-stored quote handle. Pass it to POST /intents to submit.
costCost breakdown. See below.
signDataEIP-712 typed data to sign. signData.origin[] has one entry per source chain; signData.destination is the destination signature.
tokenRequirementsApprovals or ETH wrapping the user must complete before signing. EOAs only — smart accounts handle this automatically.

cost

The cost object on each route describes what the user pays:
FieldDescription
inputTokens spent. Array of { chainId, tokenAddress, symbol, decimals, price, amount }.
outputTokens delivered to the recipient on the destination chain. Same shape as input.
fees{ total: { usd }, breakdown: { gas, swap, bridge } }. Each breakdown entry has { usd, sponsored }sponsored reflects what was actually covered for this route, given the request’s sponsorSettings and the project’s sponsorship balance.
const inputAmount = route.cost.input[0].amount;
const gasUSD = route.cost.fees.breakdown.gas.usd;
const totalFeeUSD = route.cost.fees.total.usd;

Choosing a different route

routes[] is server-ranked, so routes[0] is the default pick. If you want a different one — cheaper, faster, on a specific settlement layer — iterate routes and submit the chosen route’s intentId. No extra parameter is needed; the API selects the quote by intentId.
// Pick the fastest route under a $1 fee cap.
const fastest = routes
  .filter((r) => r.cost.fees.total.usd <= 1)
  .reduce((a, b) =>
    a.estimatedFillTime.seconds <= b.estimatedFillTime.seconds ? a : b
  );

await fetch(`${baseUrl}/intents`, {
  method: "POST",
  headers: { /* ... */ },
  body: JSON.stringify({
    intentId: fastest.intentId,
    signatures: { /* signed against fastest.signData */ },
  }),
});
Each route carries its own signData, so always sign against the route you intend to submit — signatures from one route won’t verify against another.

Executions (calls)

You can run executions on behalf of the EOA on the destination chain. For EOAs, executions run in the context of an intermediary contract — not the user’s account. If you receive any tokens (vault shares, swap output, etc.), include an explicit transfer call to send them back to the EOA.
const payload = {
  // …
  destinationExecutions: [
    // Deposit USDC to a vault
    {
      to: VAULT_CONTRACT,
      value: 0n,
      data: encodeFunctionData({
        abi: vaultAbi,
        functionName: 'deposit',
        args: [usdcAmount],
      }),
    },
    // Send vault receipt token back to the EOA
    {
      to: USDC_VAULT_CONTRACT,
      value: 0n,
      data: encodeFunctionData({
        abi: erc20Abi,
        functionName: 'transfer',
        args: [tokenAmount, EOA_ADDRESS],
      }),
    }
  ],
}

Sponsorship

Mark the intent as sponsored (covering gas and bridging costs for the user) by setting sponsorSettings:
Sponsor the Intent
const payload = {
  destinationChainId: "eip155:8453",
  tokenRequests: [
    {
      tokenAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      amount: "5000000",
    },
  ],
  account: {
    address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
    accountType: "EOA",
  },
  options: {
    sponsorSettings: {
      gas: true,
      bridgeFees: true,
      swapFees: false,
    },
  },
};

Source chain / token

Select which tokens and/or chains to use as the source of funds via accountAccessList. To limit the source of funds to specific chains:
Select Input Chains
const payload = {
  // …
  accountAccessList: {
    chainIds: ["eip155:10", "eip155:8453"],
  },
};
To limit the source of funds to specific tokens:
Select Input Tokens
const payload = {
  // …
  accountAccessList: {
    tokens: ["USDC", "0x4200000000000000000000000000000000000006"],
  },
};
To limit the source of funds to specific chains and tokens:
Select Input Chains and Tokens
const payload = {
  // …
  accountAccessList: {
    chainIds: ["eip155:10", "eip155:8453"],
    tokens: ["USDC"],
  },
};
or:
Select Input Chains and Tokens
const payload = {
  // …
  accountAccessList: {
    chainTokens: {
      "eip155:10": ["USDC"],
      "eip155:8453": ["WETH"],
    },
  },
};

Auxiliary funds

auxiliaryFunds declares balances that aren’t visible to the orchestrator yet but will be available by the time the intent settles. Use it to quote ahead of an inflow — a pending CEX deposit, a vault withdrawal, an unstake, or any other balance that will arrive before fill.
const payload = {
  // …
  auxiliaryFunds: {
    "eip155:8453": {
      "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913": "5000000",
    },
  },
};
Don’t list funds the account already holds — the orchestrator picks those up automatically, and adding them via auxiliaryFunds double-counts the balance and inflates the input amount in the quote.
For tokens produced by a source call (a vault exit, unwrap, unstake), declare them via provides on the call itself — not here. auxiliaryFunds and accountAccessList solve different problems: accountAccessList restricts which existing balances the router is allowed to spend, while auxiliaryFunds adds expected balances the router otherwise can’t see. They can be combined.

Swaps

If the destination token differs from the user’s source token, Warp handles the bridge and swap automatically. No additional parameters are needed — just specify the token you want on the destination chain. In a swap quote, cost.input and cost.output show different tokens:
{
  "cost": {
    "input": [
      {
        "chainId": "eip155:8453",
        "tokenAddress": "0x4200000000000000000000000000000000000006",
        "symbol": "WETH",
        "decimals": 18,
        "price": { "usd": 2412.37 },
        "amount": "959454558006521"
      }
    ],
    "output": [
      {
        "chainId": "eip155:10",
        "tokenAddress": "0x0b2c639c533813f4aa9d7837caf62653d097ff85",
        "symbol": "USDC",
        "decimals": 6,
        "price": { "usd": 0.99 },
        "amount": "2000000"
      }
    ],
    "fees": {
      "total": { "usd": 0.31 },
      "breakdown": {
        "gas": { "usd": 0.30, "sponsored": false },
        "swap": { "usd": 0.01, "sponsored": false },
        "bridge": { "usd": 0.0004, "sponsored": false }
      }
    }
  }
}
Here the user spends WETH on Base (eip155:8453) to receive USDC on Optimism. output.amount matches the requested amount exactly — fees are paid in input tokens, not deducted from the output. Compare input.amount × input.price.usd to output.amount × output.price.usd to see the cost.

Next Steps

Token Requirements

What the intent requirements are and how to fulfill them