Skip to main content
This guide demonstrates how to use the viem framework and the CCTP V2 API in a simple script that enables a user to transfer USDC from a wallet address on the Ethereum Sepolia testnet to another wallet address on the Avalanche Fuji testnet.

Prerequisites

Before you start building the sample app to perform a USDC transfer, ensure you have met the following prerequisites:
  1. Install Node.js and npm
    • Download and install Node.js directly or use a version manager like nvm.
    • npm is included with Node.js.
  2. Set up a non-custodial wallet (for example, MetaMask)
    • You can download, install, and create a MetaMask wallet from its official website.
    • During setup, create a wallet on the Ethereum Sepolia testnet.
    • Retrieve the private key for your wallet, as it will be required in the script below.
  3. Fund your wallet with testnet tokens

Project setup

To build the script, first set up your project environment and install the required dependencies.
  1. Set up a new project
Create a new directory and initialize a new Node.js project with default settings:
Shell
This also creates a default package.json file.
  1. Install dependencies
In your project directory, install the required dependencies, including viem:
Shell
This sets up your development environment with the necessary libraries for building the script. It also updates the package.json file with the dependencies.
  1. Add module type
Add "type": "module" to the package.json file:
package.json
  1. Configure environment variables
Create a .env file in your project directory and add your wallet private key:
Shell
Warning: This is strictly for testing purposes. Never share your private key.

Script setup

This section covers the necessary setup for the transfer.js script, including defining keys and addresses, and configuring the wallet client for interacting with the source and destination chains.
  1. Replace with your private key and wallet address
Ensure that this section of the file includes your private key and associated wallet address. The script also predefines the contract addresses, the transfer amount, and the max fee. These definitions are critical for successfully transferring USDC between the intended wallets.
Javascript
  1. Set up wallet clients
The wallet client configures the appropriate network settings using viem. In this example, the script connects to the Ethereum Sepolia testnet and the Avalanche Fuji testnet.
Javascript

CCTP transfer process

The following sections outline the relevant transfer logic of the sample script. You can view the full source code in the Build the script section below. To perform the actual transfer of USDC from Ethereum Sepolia to Avalanche Fuji using CCTP V2, follow the steps below:

1. Approve USDC

The first step is to grant approval for the TokenMessengerV2 contract deployed on the Ethereum Sepolia testnet to withdraw USDC from your wallet on that source chain. This allows the contract to withdraw USDC from the specified wallet address.
Javascript

2. Burn USDC

In this step, you call the depositForBurn function from the TokenMessengerV2 contract deployed on the Ethereum Sepolia testnet to burn USDC on that source chain. You specify the following parameters:
  • Burn amount: The amount of USDC to burn
  • Destination domain: the target blockchain for minting USDC
  • Mint recipient: The wallet address that will receive the minted USDC
  • Burn token: The contract address of the USDC token being burned on the source chain
  • Destination caller: The address on the target chain to call receiveMessage
  • Max fee: The maximum fee allowed for the transfer
  • Finality threshold: Determines whether it’s a Fast Transfer or a Standard Transfer
Javascript

3. Retrieve attestation

In this step, you retrieve the attestation required to complete the CCTP transfer.
  • Call Circle’s GET /v2/messages API endpoint to retrieve the attestation.
    • Pass the srcDomain argument from the CCTP Domain for your source chain.
    • Pass transactionHash from the value returned by sendTransaction within the burnUSDC function above.
This step is essential for verifying the burn event before proceeding with the transfer.
Javascript

4. Mint USDC

In this final step, you call the receiveMessage function from the MessageTransmitterV2 contract deployed on the Avalanche Fuji testnet to mint USDC on that destination chain.
  • Pass the signed attestation and the message data as parameters.
  • The function processes the attestation and mints USDC to the specified Avalanche Fuji wallet address.
This step finalizes the CCTP transfer, making the USDC available on the destination chain.
Javascript

Build the script

Now that you understand the core steps for programmatically transferring USDC from Ethereum Sepolia to Avalanche Fuji using CCTP V2, create a transfer.js in your project directory and populate it with the sample code below.
Note: The source wallet must contain native testnet tokens (to cover gas fees) and testnet USDC to complete the transfer.

transfer.js

Javascript
The transfer.js script provides a complete end-to-end solution for transfering USDC in CCTP V2 with a non-custodial wallet. In the next section, you can test the script.

Test the script

To test the script, run the following command:
Shell
Once the script runs and the transfer is finalized, a confirmation receipt is logged in the console.
Rate Limit:The attestation service rate limit is 35 requests per second. If you exceed this limit, the service blocks all API requests for the next 5 minutes and returns an HTTP 429 (Too Many Requests) response.
You have successfully transferred USDC between two EVM-compatible chains using CCTP end-to-end!
WHAT’S NEXT