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

# Transfer Execution

> Submit on-chain transfers using Gas API quotes and CashmereCCTP contracts.

import { Tabs, Tab, Callout } from 'mintlify';

## Overview

Cashmere does not expose a custodial `/transfer` REST endpoint. Transfers happen **on-chain** using the smart contract interfaces, powered by fees and signatures generated via the Gas API.

The high-level flow:

1. Fetch fees and signatures from the Gas API (`/getEcdsaSig_native` or `/getEd25519Sig_native`).
2. Populate the appropriate `TransferParams` / `TransferV2Params`.
3. Call the contract on the origin chain.
4. Monitor settlement using the Monitoring API (`/transactions` or `/transactionsmainnet`).

***

## Step-by-Step (EVM)

<Tabs>
  <Tab title="1. Quote" icon="bolt">
    ```ts theme={null}
    const res = await fetch(
      'https://gas.cashmere.exchange/getEcdsaSig_native?' +
        new URLSearchParams({
          localDomain: '0',          // Ethereum
          destinationDomain: '3',    // Arbitrum
          isV2: 'true',
          isNative: 'false',
        })
    );
    const quote = await res.json();
    ```
  </Tab>

  <Tab title="2. Prepare Params" icon="list-check">
    ```ts theme={null}
    import { zeroPadValue, parseUnits } from 'ethers';

    const isNative = Boolean(useNativeFees);
    const amount = parseUnits('100', 6);
    const gasDropAmount = isNative
      ? parseUnits(nativeGasDrop, nativeDecimals)
      : parseUnits(usdcGasDrop, 6);

    const minFeeBps = await fetchMinimumFeeBps(localDomain, destinationDomain);
    const maxFee = ceilDiv(amount * BigInt(minFeeBps ?? 100), 10_000n);

    const params = {
      amount,
      maxFee,
      fee: BigInt(quote.fee),
      deadline: BigInt(quote.deadline),
      gasDropAmount,
      destinationDomain,
      minFinalityThreshold: 1_000,
      recipient: zeroPadValue(destinationAddress, 32),
      solanaOwner: ZERO_BYTES_32,
      isNative,
      hookData: '0x00',
      signature: quote.signature,
    };
    ```
  </Tab>

  <Tab title="3. Send Tx" icon="rocket-launch">
    ```ts theme={null}
    const cashmere = loadCashmereContract(signer);
    await ensureAllowance({ usdc, params });

    const overrides = params.isNative
      ? { value: params.fee + params.gasDropAmount }
      : {};

    const tx = await cashmere.transferV2(params, overrides);
    await tx.wait();
    ```
  </Tab>
</Tabs>

<Callout type="warning">
  Quotes expire in \~100 seconds. Submit the transaction immediately after fetching the signature.
</Callout>

<Callout type="info">
  Circle publishes recommended `minimumFee` values per domain via `https://iris-api.circle.com/v2/burn/USDC/fees/{sourceDomainId}/{destDomainId}`. Align `maxFee` with the returned value for your selected `finalityThreshold` (`1000` for Fast, `2000` for Normal) before submitting `transferV2*` transactions.

  Bridging into Solana? The `recipient` must be the hex-encoded USDC ATA for the destination wallet and `solanaOwner` must contain that wallet’s 32-byte public key.
</Callout>

***

## Step-by-Step (Solana)

1. Fetch an Ed25519 signature (`version=2` for `transfer_v2` routes).
2. Convert the destination Solana wallet into its USDC Associated Token Account (ATA) and encode both ATA + owner as 32-byte hex.
3. Add an `Ed25519Program.createInstructionWithPublicKey` instruction using the quote payload, then call `transfer_v2` with the same fee/deadline values and required PDAs (see Smart Contracts guide for the full account list).

***

## Permit Variants

* EVM `transferWithPermit` / `transferV2WithPermit` accept a `PermitParams` struct. Sign EIP-2612 locally, then call the contract with the same Gas API response.
* Non-EVM chains do not support permit flows; approval/revocation is handled by their native token standards.

***

## Monitoring Settlement

| Endpoint                                                 | Description                                                                 |
| -------------------------------------------------------- | --------------------------------------------------------------------------- |
| `GET https://kapi.cashmere.exchange/transactions`        | Combined testnet dataset.                                                   |
| `GET https://kapi.cashmere.exchange/transactionsmainnet` | Production transactions (supports cursor pagination and timestamp filters). |
| `GET https://gas.cashmere.exchange/subscribe`            | WebSocket notifications for fee updates (no settlement data).               |

The transaction payload includes `relayer_fee`, `gas_drop_amount`, `destination_tx_hash`, and status fields you can use for dashboards or reconciliation.

***

## Common Pitfalls

* **Signature mismatch** – Verify that `isV2`, `isNative`, and the domain IDs match the contract function you intend to call.
* **Allowance errors** – When `isNative=false`, approve `amount + gasDropAmount` USDC.
* **Native fee shortfall** – When `isNative=true`, attach `fee + gasDropAmount` wei as `msg.value`.
* **Expired deadline** – Fetch a fresh signature if the transaction is not broadcast within the 100-second validity window.
