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

# Native Swap Example

> Create a simple asset swap on Citrea backed by collateral on Ethereum sepolia

# Guide: Native Swap Example

This guide provides a complete, code-first walkthrough for creating and submitting a swap transaction using the API. We will build a real-world example: swapping USD to cBTC on the Citrea blockchain backed by Sepolia ETH as collateral, using [Crest](https://x.com/crest_btc) as a liquidity source.

## The Goal

Our goal is to create an "intent" that performs the following actions:

1. **On Sepolia Testnet**: A user deposits `0.0001` Sepolia ETH into an escrow EOA.
2. **On Citrea Testnet**: Using the value from the deposit, execute a swap for cBTC via `crest` contract.
3. **Finally**: The solver sends the principal amount of the deposit back to the user on Citrea.

This entire process will be defined in a single intent, signed by the user once, and submitted to the API.

## Prerequisites

You'll need `viem` to interact with chains, create authorizations, and sign messages. For frontend applications, you would need to use `privy` SDK to work with embedded wallets.

```typescript theme={null}
import {
  createWalletClient,
  http,
  parseUnits,
  getAddress,
  formatEther
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { citreaTestnet, sepolia } from "viem/chains";
```

## Step 1: Setting up Accounts and Clients

First, we define the accounts and blockchain clients we'll be working with. In a real application, the `user` would be the end-user interacting with your application, and their private key would be managed by their wallet.

```typescript theme={null}
// A sample user account
const user = privateKeyToAccount("0x...");

// The escrow contract address where the initial deposit is sent
const escrowAddress = getAddress("0x...");


const publicSepoliaClient = createPublicClient({
  chain: sepolia,
  transport: http(),
});

const publicCitreaClient = createPublicClient({
  chain: citreaTestnet,
  transport: http(),
});
```

## Step 2: Define the Intent Parameters

We'll define the amounts and generate a quote for the swap part of our intent.

```typescript theme={null}
const depositAmount = parseUnits("0.0001", 18);

// In a real app, you would call an external service like crest's /rfqt endpoint
// to get a signed quote for the swap.
const crestRfqt = await generateRfqt({
  quoteId: "0x...",
  user: user.address,
  tokenIn: "usd",
  tokenOut: "bitcoin",
  amountIn: formatEther(depositAmount),
  amountOut: "100", // Targeting 100 USD
  expiry: Math.floor(Date.now() / 1000) + 60, // 1 minute expiry
});
```

## Step 3: Create EIP-7702 Authorizations

The core of the process is the user granting our system one-time authority on each chain. The user's wallet will sign an EIP-7702 authorization for each `delegate` contract on each chain.

```typescript theme={null}
// Fetch the current nonce for the user on each chain
const nonceSepolia = await publicSepoliaClient.getTransactionCount({address: user.address});
const nonceCitrea = await publicCitreaClient.getTransactionCount({address: user.address});

const delegateAddressSepolia = getAddress("0x36d5e6b93c211b79b734b0adb3812d0c066608f9");
const delegateAddressCitrea = getAddress("0x446448759096065EE9c173452024D5F9660Ec816");

// User signs an authorization for Sepolia
const userAuthSepolia = await user.signAuthorization({
  address: delegateAddressSepolia,
  chainId: sepolia.id,
  nonce: nonceSepolia,
});

// User signs another authorization for Citrea
const userAuthCitrea = await user.signAuthorization({
  address: delegateAddressCitrea,
  chainId: citreaTestnet.id,
  nonce: nonceCitrea,
});
```

These `authorization` objects are what a solver will use to execute transactions on the user's behalf.

## Step 4: Construct the Chain Batches

Now we define the specific on-chain actions. Each object in the `chainBatches` array represents a set of calls to be executed on a specific blockchain, in order.

```typescript theme={null}
import { hashChainBatches, getIntentHash } from "../src/authorization";

const recentBlockSepolia = await publicSepoliaClient.getBlockNumber();
const recentBlockCitrea = await publicCitreaClient.getBlockNumber();

const chainBatches = hashChainBatches([
  // Step 0: Deposit Sepolia ETH to escrow
  {
    chainId: sepolia.id,
    recentBlock: recentBlockSepolia,
    calls: [
      {
        to: escrowAddress,
        data: "0x",
        value: depositAmount,
      },
    ],
  },
  // Step 1: Swap for cBTC on Citrea
  {
    chainId: citreaTestnet.id,
    // We add a buffer of 8 blocks to ensure the Sepolia transaction has time to confirm
    // before this step becomes executable.
    recentBlock: recentBlockCitrea + 8n,
    calls: [
      // The RFQT object from Step 2 is a valid "Call" object
      crestRfqt,
    ],
  },
]);
```

The `hashChainBatches` utility processes this structure to create the hashes that will be signed.

## Step 5: Sign the Intent and Prepare the Request

Finally, the user signs the *intent* itself. The signature is over the computed hash of the `chainBatches`. This proves the user agrees to this specific sequence of actions.

```typescript theme={null}
// Create the digest that the user will sign
const digest = getIntentHash(chainBatches);

// User signs the message
const signature = await user.signMessage({
  message: {
    raw: digest,
  },
});

// Assemble the final request body for the API
const apiRequest = {
  address: user.address,
  authorization: [userAuthSepolia, userAuthCitrea],
  intentAuthorization: {
    signature,
    chainBatches,
  },
  tokenAddress: "0x0", // Native token
  tokenAmount: depositAmount,
};
```

This `apiRequest` object is what you send to the `POST /transaction/submit` endpoint.

```bash theme={null}
curl -X POST https://tx-api.spicenet.io/transaction/submit \
  -H "Content-Type: application/json" \
  -d '{
    "address": "0x...",
    "authorization": [ { ... }, { ... } ],
    "intentAuthorization": {
      "signature": "0x...",
      "chainBatches": [ { ... }, { ... } ]
    },
    "tokenAddress": "0x0",
    "tokenAmount": 100000000000000
  }'
```

## What Happens Next: The Solver

After you submit the intent, the API makes it available to a network of solvers. A solver will:

1. Pick up your intent.
2. Execute **Step 0** by sending a transaction to the `Delegate` contract on Sepolia, using your signed authorization. This deposits your funds to escrow.
3. Wait for the required block confirmations.
4. Execute **Step 1** by sending a transaction to the `Delegate` contract on Citrea, which performs the swap.
5. As part of the final transaction, the solver also transfers the principal deposit amount (`tokenAmount`) back to your address (`address`) on the destination chain (Citrea).

Your application can track the status of the intent using the `GET /intent/{intentId}/step/{stepId}/status` endpoint.

You have successfully orchestrated a cross-chain action without requiring the user to switch networks or manage gas on the destination chain.
