Skip to main content
This guide walks you through the process of creating Unified Crosschain USDC Balances on supported EVM chains using Circle Gateway, and performing transfers from EVM to EVM and from Solana to EVM.
Use Unified Balance Kit to simplify this integration.This quickstart uses a manual Gateway integration. It is for learning or for developers who need direct control.To simplify, use Unified Balance Kit to deposit and spend USDC in just a few lines of code.
Select a tab below for the Circle Wallets or self-managed wallet path.

Prerequisites

This quickstart uses Arc Testnet for deposits and the Arc Testnet -> Base Sepolia route for the EVM transfer example. You can adapt the same code to other supported EVM testnets later in the guide.Before you begin, ensure that you’ve:If you want to try the Solana to EVM transfer, ensure that you’ve:If you want to use the Direct Mint path for Solana to EVM, also create an EVM Developer-Controlled Wallet on the destination chain to submit the mint transaction.

Add testnet funds to your wallet

To interact with Gateway, you need test USDC and native tokens in your wallet on each chain you deposit from. In the default Arc Testnet deposit flow, the same USDC also covers transaction fees because Arc uses USDC as the native gas token.Use the Circle Faucet to get test USDC. If you have a Circle Developer Console account, you can use the Console Faucet to get testnet native tokens. In addition, the following faucets can also be used to fund your wallet with testnet native tokens:
Faucet: Arc Testnet (USDC + native tokens)
PropertyValue
Chain namearcTestnet
USDC address0x3600000000000000000000000000000000000000
Domain ID26

Step 1. Set up your project

1.1. Create the project and install dependencies

If you want to try the Solana to EVM transfer, add the run script and install these additional dependencies:

1.2. Configure TypeScript (optional)

This step is optional. It helps prevent missing types in your IDE or editor.
Create a tsconfig.json file:
Then, update the tsconfig.json file:

1.3. Set environment variables

Create a .env file in the project directory:
.env
  • CIRCLE_API_KEY is your Circle API key.
  • CIRCLE_ENTITY_SECRET is your Circle entity secret.
  • DEPOSITOR_ADDRESS is the source depositor wallet for the script you are running.
  • RECIPIENT_ADDRESS is the destination wallet. It is only required for transfer scripts.
For transfer-from-evm.ts, both DEPOSITOR_ADDRESS and RECIPIENT_ADDRESS are EVM addresses.For transfer-from-sol.ts, DEPOSITOR_ADDRESS is a Solana address and RECIPIENT_ADDRESS is an EVM address.
For the Circle Wallets Direct Mint path, RECIPIENT_ADDRESS must be a destination-chain Developer-Controlled Wallet address in your Circle account. The script uses createContractExecutionTransaction() to submit gatewayMint() from that wallet, so a regular external EVM address will not work.
Open .env in your editor rather than writing values with shell commands, and add .env to your .gitignore. This prevents credentials from leaking into your shell history or version control.

Step 2. Set up the configuration file

The deposit and transfer scripts share this configuration file.

2.1. Create the configuration file

2.2. Configure shared Gateway constants

Add the shared Gateway constants used by the deposit and transfer scripts. To swap chains later, keep chainConfig as the shared map and update the SOURCE_CHAIN and DEST_CHAIN constants inside each script.
config.ts

Step 3. Deposit into a unified crosschain balance (Circle Wallets)

The deposit script deposits USDC into the Gateway Wallet on Arc Testnet. You can skip to the full deposit script if you prefer.
Do not transfer USDC directly to the Gateway Wallet contract with a standard ERC-20 transfer. You must call a Gateway deposit method or the USDC will not be credited to your unified balance.

3.1. Create the deposit script

3.2. Define constants and deposit amount

Set the deposit amount near the top of the script. This example uses Arc Testnet as the source chain, and you can swap chains later by changing SOURCE_CHAIN.

3.3. Approve USDC spending and submit the deposit

The script first approves the Gateway Wallet contract to spend USDC, then calls the Gateway deposit(address,uint256) method on the configured source chain.

3.4. Wait for Circle Wallet transaction to complete

Circle Wallet contract execution is asynchronous. After each submit step, wait for transaction completion before proceeding to the next phase.

3.5. Full deposit script (Circle Wallets)

The script approves USDC spending and deposits into the Gateway Wallet on the configured source chain. Inline comments explain each stage.
deposit.ts

3.6. Run the deposit script

Run the script:
Wait for the required number of block confirmations. Once the deposit transactions are final, the total balance is the sum of all the USDC from deposit transactions across all supported chains that have reached finality.If you later adapt this deposit script to another EVM chain, update SOURCE_CHAIN to another supported entry in chainConfig.

3.7. Check the balances on the Gateway Wallet

Create a new file called balances.ts, and add the following code. This script retrieves the USDC balances available from your Gateway Wallet for the DEPOSITOR_ADDRESS currently set in .env.
balances.ts
You can run it to check whether finality has been reached for recent transactions.

Step 4. Transfer USDC from EVM to EVM

This step transfers USDC from your Arc Testnet Gateway balance to Base Sepolia. Both paths create and submit the burn intent from Arc Testnet first. Direct Mint then retrieves the Gateway attestation and calls gatewayMint(...) on Base Sepolia from your wallet, while the Forwarding Service lets Circle complete the destination mint for you.

4.1. Create the EVM transfer script (Circle Wallets)

You can skip to the full transfer script if you prefer.

4.2. Define constants and types

This script uses Arc Testnet as the source chain and Base Sepolia as the destination chain.This direct-mint flow signs the burn intent on Arc Testnet, requests the Gateway attestation, and then calls gatewayMint(...) on Base Sepolia from your wallet.

4.3. Add shared chain references

The script uses the shared chain map from config.ts.

4.4. Create and sign the burn intent

Create an EIP-712 burn intent for the Arc Testnet Gateway balance and sign it with the source Developer-Controlled Wallet.

4.5. Request the Gateway attestation

Send the signed burn intent to the Gateway API and validate that the response includes both the attestation and the operator signature needed for minting.

4.6. Mint on Base Sepolia

Once the Gateway API returns the attestation set, call gatewayMint(bytes,bytes) on Base Sepolia and wait for Circle Wallet transaction completion.

4.7. Full EVM direct-mint script (Circle Wallets)

The script builds and signs a burn intent for Arc Testnet, requests the Gateway attestation, and mints on Base Sepolia. Inline comments explain each stage.
transfer-from-evm.ts

4.8. Run the EVM direct-mint script

Run the script to burn from your Arc Testnet Gateway balance and call gatewayMint(...) on Base Sepolia.Confirm these values before running:
  • DEPOSITOR_ADDRESS is the source Arc Testnet wallet
  • RECIPIENT_ADDRESS is the destination Base Sepolia wallet
  • the source depositor has a Gateway balance on Arc Testnet
  • the destination wallet can submit the mint transaction on Base Sepolia
Gateway fees are charged per burn intent and are based on the source blockchain you burn from. Choosing where to hold and burn Gateway balances can affect transfer costs. For fee details, see Gateway Fees.
When the transfer succeeds, the script logs the minted amount and mint transaction ID.