Overview

Rhinestone supports two types of swaps: injected and solver-based. Injected swaps let you tap into onchain liquidity using DEX aggregators like 1inch and 0x. It requires some additional setup, but provides great token coverage, deep liquidity, and best-in-class price execution. Solver-based swaps use relayer liquidity to make swaps. They are simpler to get started, but are limited in token support that is bound by relayer liquidity.

Injected Swaps

We will use 1inch API to make a WETH -> cbBTC swap on Base chain using funds on Arbitrum. First, let’s initialize 1inch API client:
const walletAddress = rhinestoneAccount.getAddress()
const wethBase = '0x4200000000000000000000000000000000000006'
const wethAmount = parseEther("0.1")
const cbbtcBase = '0xcbb7c0000ab88b473b1f5afd9ef808440eed33bf'

const oneInchApiKey = 'YOUR_1INCH_API_KEY'

const config = {
  tokenAddress: wethBase,
  amountToSwap: wethAmount,
  dstToken: cbbtcBase,
  slippage: 1,
};

async function call1inchAPI<T>(
  endpointPath: string,
  queryParams: Record<string, string>
): Promise<T> {
  function buildQueryURL(path: string, params: Record<string, string>): string {
    const url = new URL(baseUrl + path);
    url.search = new URLSearchParams(params).toString();
    return url.toString();
  }

  const url = buildQueryURL(endpointPath, queryParams);

  const response = await fetch(url, {
    method: "GET",
    headers: {
      Accept: "application/json",
      Authorization: `Bearer ${oneInchApiKey}`,
    },
  });

  if (!response.ok) {
    const body = await response.text();
    throw new Error(`1inch API returned status ${response.status}: ${body}`);
  }

  return (await response.json()) as T;
}
Then, let’s fetch the allowance data and get the swap quote:
const approveTx = await call1inchAPI<ApproveTransactionResponse>(
  "/approve/transaction",
  {
    tokenAddress: config.tokenAddress,
    amount: config.amountToSwap.toString(),
  }
);

console.log("Approval transaction details:", approveTx);

const swapTx = await call1inchAPI<TxResponse>("/swap", {
  src: config.tokenAddress,
  dst: config.dstToken,
  amount: config.amountToSwap.toString(),
  from: walletAddress,
  slippage: config.slippage.toString(),
  disableEstimate: "false",
  allowPartialFill: "false",
});

console.log("Swap transaction details:", approveTx);
Finally, let’s submit the swap transaction:
const transferIntent = await rhinestoneAccount.sendTransaction({
  sourceChains: [arbitrum],
  targetChain: base,
  calls: [
    {
      to: approveTx.to,
      data: approveTx.data,
      value: approveTx.value,
    },
    {
      to: swapTx.tx.to,
      data: swapTx.tx.data,
      value: swapTx.tx.value,
    },
  ],
  tokenRequests: [
    {
      address: wethBase,
      amount: wethAmount,
    },
  ],
})
This will bridge the funds from Arbitrum to get 0.1 WETH on Base, then make a swap to cbBTC using 1inch.

Solver-based swaps

With Rhinestone, you can automatically swap your tokens when executing the transaction using relayer liquidity. Say, you only have USDC on Base but want to transact with ETH on Arbitrum. In that case, you only need to specify the required tokens on the target chain, and Omni Account will do the bridging and the swap in one go. To make your first cross-chain swap, make sure that:
  1. The account is deployed on any chain.
  2. The account has at least one of the supported assets on the chain with the deployed account.
const ethTarget = getTokenAddress('ETH', arbitrumSepolia.id)
const ethAmount = 2n
const receiver = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'

const transaction = await rhinestoneAccount.sendTransaction({
  sourceChains: [baseSepolia],
  targetChain: arbitrumSepolia,
  calls: [
    {
      to: receiver,
      value: ethAmount,
    },
  ],
  tokenRequests: [
    {
      address: ethTarget,
      amount: ethAmount,
    },
  ],
})
Assuming you had USDC on Base Sepolia, this will swap some of that USDC to ETH, send it to Arbitrum Sepolia, and execute the transfer transaction.
Make sure the token address in calls and tokenRequests corresponds to the target chain.