Skip to main content
Approve the source TokenManager, fetch a fee quote from Iris, and initiate a fast transfer of EURC from Ethereum Sepolia to Base Sepolia. This route uses the sandbox EURC token ID that Iris lists on domains 0 and 6. The same pattern applies to any registered token—swap in another tokenId and destination domain as needed.
This quickstart uses fast transfer (minFinalityThreshold = 1000). Fast transfers require Iris FX pricing to be configured for the token. If Iris returns FX_SYMBOL_NOT_CONFIGURED, use standard transfer instead (minFinalityThreshold = 2000, omit PRE_FINALITY from the quote requests array). See step 7 for details.

Prerequisites

Before you begin, ensure that you’ve:
  • Installed Node.js v22+
  • Prepared an EVM testnet wallet with the private key available
    • Added Base Sepolia to your wallet
  • Funded your wallet with the following testnet tokens:
    • Sepolia ETH (native token) from a public faucet
    • Sepolia EURC from the Circle Faucet
    • Base Sepolia ETH if you plan to submit the destination mint yourself

Step 1: Set up the project

1.1. Create the project and install 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

Open .env in your editor and add:
  • PRIVATE_KEY is the private key for the Ethereum Sepolia EOA that signs the source chain approval and transfer transactions. The direct-mint path also uses the same key to submit the destination mint on Base.
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.
The npm run start command loads variables from .env using Node.js native env-file support.
This example uses one or more private keys for local testing. In production, use a secure key management solution and never expose or share private keys.

Step 2: Configure clients and addresses

Create index.ts and configure clients for Ethereum Sepolia and Base Sepolia.
TypeScript
The Base wallet is only required for the direct mint path. For forwarded mint, basePublic is enough to confirm the destination balance.

Step 3: Fetch token metadata

Query the Iris API to retrieve the token’s decimal precision. Use the returned decimals value to express the transfer amount in the token’s smallest unit. EURC uses 6 decimals.
TypeScript

Step 4: Approve the source TokenManager

Approval goes to the per-token TokenManager, not to CrossChainTokenService. Read the local TokenManager address from the service, then call approve on the token.
TypeScript

Step 5: Check the fast transfer allowance

This quickstart uses a fast transfer (minFinalityThreshold = 1000), which consumes per-token fast burn allowance. Confirm remaining capacity before you quote fees.
TypeScript

Step 6: Get a fee quote

Both paths call the same Iris fee-quote endpoint. Forwarding is selected in the quote requests array—not by a different source chain function. Use Forwarded mint to have Circle complete the destination mint, or Direct mint to submit receiveMessage yourself.
Include a FORWARD request so the quote covers destination mint gas. Pass the Base recipient as destinationAddress in the forward params.
TypeScript

Step 7: Initiate the transfer

Call crossChainTransfer on the source service. The onchain call is the same for both completion paths. The example uses bytes32(0) for destinationCaller to allow permissionless relay, and 1000 for minFinalityThreshold to use a fast transfer. For standard finality, use 2000 instead and omit PRE_FINALITY from the quote—see Transfer finality and fast burn allowance. On EVM, destinationAddress must be the raw packed 20-byte address. Do not ABI-encode it to 32 bytes.
TypeScript

Step 8: Complete the transfer on Base

Choose the completion path that matches the fee quote you requested in Step 6.
When the quote includes FORWARD, Circle submits the destination mint. Resolve the token on Base and wait until the recipient balance increases.
TypeScript
After the transfer completes, the recipient holds the transferred EURC on Base. Verify by reading the recipient’s balance on the Base deployment (0x808456652fdb597867f38412077A9182bf77359F).