Skip to main content
Transfer your unified USDC balance to a destination chain without needing a wallet or gas on that chain. The Forwarding Service handles the destination chain mint automatically. This guide demonstrates how to estimate fees, create a burn intent, submit it with forwarding enabled, and poll for transfer completion. Select a tab below for EVM or Solana destination instructions.

Prerequisites

Before you begin, ensure that you’ve:
  • Installed Node.js v22.6+
  • Prepared an EVM testnet wallet with the private key available
    • Added the supported Testnets of your choice to your wallet (this guide uses Arc Testnet and Base Sepolia)
  • Funded your testnet wallet with native tokens on the source chain (this guide uses Arc Testnet). With the Forwarding Service, you do not need native tokens on the destination chain.
  • Deposited 10 USDC into the Gateway Wallet contract on Arc Testnet
  • Created a TypeScript project and have viem installed
  • You’ve set up a .env file with the following variables:
    .env

Steps

Follow these steps to transfer a unified USDC balance using the Forwarding Service. This example transfers 10 USDC from Arc Testnet to Base Sepolia. You can adapt it for another supported chain.

Step 1. Create the transfer spec and estimate fees

Create a new file called transfer.ts in the root of your project and add the following code to it. This code creates a transfer spec for 10 USDC on Arc Testnet, then calls the /estimate endpoint with enableForwarder=true to determine the maxFee and maxBlockHeight values. Using the estimate endpoint ensures the maxFee covers the gas fee, transfer fee, and forwarding fee.
transfer.ts
Note: For production apps, verifying the balance on each chain before creating burn intents is best practice. For this how-to, it’s assumed that the balance is created per the prerequisites. For a complete end-to-end example that includes checking and error handling, see the Gateway quickstarts (EVM).

Step 2. Sign and submit the burn intent to the Gateway API

Add the following code to transfer.ts. This code constructs the EIP-712 typed data, signs the burn intent using the estimated maxFee and maxBlockHeight, and submits it to the /transfer endpoint with enableForwarder=true.
In forwarded flows, the POST /v1/transfer response may omit top-level attestation and signature fields. Use the returned transferId to poll GET /v1/transfer/{id} for the full transfer record.
transfer.ts

Step 3. Poll for transfer completion

Add the following code to transfer.ts. Because the Forwarding Service handles the destination chain mint, you don’t need to call the minter contract. Instead, poll the /transfer/{id} endpoint until the status reaches confirmed or finalized.
transfer.ts

Step 4. Run the script

Run the script with the following command: