Skip to main content
Multi-chain intents let you make cross-chain transactions. Those intents specify both the target (destination) and the source chain(s). The actual transaction (fill) happens on the target chain, while the funds are taken on the source chains (claims). Specifying source chains is optional. Rhinestone finds the optimal path automatically. Multi-chain intents work similarly to single-chain intents, but with the introduction of settlement layers. From your perspective, making cross-chain transactions is as simple as making normal Ethereum transactions. The Rhinestone Orchestrator handles path finding, liquidity management, and intent execution for you. Learn more about how Rhinestone intents work here.

Example

We will make a cross-chain token transfer using multi-chain intents.

Source Chain

Providing the source chain deploys the account on that chain, as well as uses the funds on that chain to fulfill the intent. If you already have an account deployed on one or more source chains, you can omit the sourceChain. In that case, the orchestrator will use the best chain(s) to source funds.

Token Requests

tokenRequests is a list of token assets and their amounts that are required on the target chain to make the transaction. It tells the solvers to ensure those assets are present before executing the transaction calls. If you don’t need any assets on the target chain, you can omit this.

Gas Limit

You can override the default gas limit for the target chain execution with gasLimit. Doing this will make the intent better priced, because we can more accurately calculate the fee that a solver needs to be reimbursed with for paying the gas. If this is not provided, we calculate using a gas limit of 1_000_000.

Source Assets

You can specify what token (or tokens) to use as an input asset:
You can also specify source assets on a per-chain basis:
Chain-specific sourceAssets take precendence over sourceChain parameter.

Settlement Layers

Rhinestone routes intents through a settlement layer. By default, the orchestrator picks the best one. Pass settlementLayers to constrain the choice — either include a specific set, or exclude one you want to avoid. Pin to a specific layer (or set of layers):
Exclude a layer (e.g. while one is degraded) and let the orchestrator pick from the rest:
The same filter works on splitIntents (see Liquidity Splitting).

Choosing a different quote

prepareTransaction returns multiple candidate routes via prepared.quotes. By default, signTransaction picks prepared.quotes.best — the orchestrator’s recommended route. To pick a different one, iterate prepared.quotes.all and pass the chosen quote’s intentId to signTransaction:
Each quote has its own signData — signatures from one quote won’t verify against another. Passing { intentId } tells the SDK to sign the matching quote.

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.
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.

Wait for Execution

submitTransaction returns once the intent has been accepted by the orchestrator. To wait until it actually settles onchain, use waitForExecution:

Get Intent Status

You can also fetch the intent status directly to implement a custom polling logic:

Liquidity Splitting

When transferring large token amounts, a single settlement layer may not have enough liquidity to fill the intent efficiently. Use splitIntents to break the amount into smaller portions that can be routed through different settlement layers in parallel, improving execution speed and pricing. First, compute the splits:
Then, send each split as a separate transaction:
You can optionally filter which settlement layers to use: