|
| 1 | +# Cross Chain USDC Transfers with Bridge Kit |
| 2 | + |
| 3 | +:::info |
| 4 | +This guide is maintained by [Circle](https://www.circle.com). |
| 5 | +::: |
| 6 | + |
| 7 | +## Overview |
| 8 | + |
| 9 | +This quickstart guide helps you write a script that transfers USDC from Base to Ethereum using [Bridge Kit](https://learn.circle.com/bridge-kit). |
| 10 | + |
| 11 | +Bridge Kit is a high-level SDK that lets you start bridging in just 10 lines of code. It provides: |
| 12 | + |
| 13 | +* **Hundreds of bridge routes** – Transfer between dozens of supported blockchains |
| 14 | +* **Simple setup** – Start bridging in 10 lines of code |
| 15 | +* **Fee collection** – Monetize your application by collecting fees from end-users |
| 16 | +* **Custom configurations** – Specify transfer speeds, custom RPC endpoints, and wallet clients |
| 17 | +* **Multiple wallet support** – Works with Viem, Ethers, MetaMask, Phantom, and more |
| 18 | +* **Smart retry capabilities** – Automatically identify and recover stuck transactions |
| 19 | + |
| 20 | +By the end, you'll know how to: |
| 21 | + |
| 22 | +* Install Bridge Kit and its dependencies |
| 23 | +* Configure your environment with private keys |
| 24 | +* Execute a cross-chain USDC transfer from Base to Ethereum |
| 25 | +* Verify the transfer on the blockchain |
| 26 | + |
| 27 | +## Steps |
| 28 | + |
| 29 | +::::steps |
| 30 | + |
| 31 | +### Prerequisites |
| 32 | + |
| 33 | +Before you begin, ensure that you've: |
| 34 | + |
| 35 | +* Installed Node.js v22+ and npm |
| 36 | +* Created an Ethereum Sepolia wallet and Base Sepolia wallet. You will fund these wallets in this quickstart. |
| 37 | + |
| 38 | +### Set up your development environment |
| 39 | + |
| 40 | +Create a new directory and install Bridge Kit and its dependencies: |
| 41 | + |
| 42 | +```bash |
| 43 | +# Setup your directory and initialize a Node.js project |
| 44 | +mkdir bridge-kit-quickstart-transfer-base-to-eth |
| 45 | +cd bridge-kit-quickstart-transfer-base-to-eth |
| 46 | +npm init -y |
| 47 | + |
| 48 | +# Install Bridge Kit and tools |
| 49 | +npm install @circle-fin/bridge-kit @circle-fin/adapter-viem-v2 viem typescript tsx dotenv |
| 50 | +``` |
| 51 | + |
| 52 | +### Initialize and configure the project |
| 53 | + |
| 54 | +First, initialize the project, which creates a `tsconfig.json` file: |
| 55 | + |
| 56 | +```bash |
| 57 | +# Initialize a TypeScript project |
| 58 | +npx tsc --init |
| 59 | +``` |
| 60 | + |
| 61 | +Then, edit the `tsconfig.json` file: |
| 62 | + |
| 63 | +```bash |
| 64 | +# Replace the contents of the generated file |
| 65 | +cat <<'EOF' > tsconfig.json |
| 66 | +{ |
| 67 | + "compilerOptions": { |
| 68 | + "target": "ESNext", |
| 69 | + "module": "ESNext", |
| 70 | + "moduleResolution": "bundler", |
| 71 | + "strict": true |
| 72 | + } |
| 73 | +} |
| 74 | +EOF |
| 75 | +``` |
| 76 | + |
| 77 | +### Configure environment variables |
| 78 | + |
| 79 | +Create a `.env` file in the project directory and add your wallet private key, replacing `{YOUR_PRIVATE_KEY}` with the private key for your Ethereum Sepolia wallet. (You can find and export your private key in MetaMask.) |
| 80 | + |
| 81 | +```bash |
| 82 | +echo "PRIVATE_KEY={YOUR_PRIVATE_KEY}" > .env |
| 83 | +``` |
| 84 | + |
| 85 | +:::warning |
| 86 | +Never commit your private key to version control. Use environment variables or a secure key management system. |
| 87 | +::: |
| 88 | + |
| 89 | +### Fund your wallets |
| 90 | + |
| 91 | +For this quickstart, you need both USDC and native tokens in your Ethereum testnet wallet and native tokens in your Base testnet wallet. If you need USDC testnet tokens, use the [Circle Faucet](https://faucet.circle.com) to get 10 USDC in your Ethereum testnet wallet. |
| 92 | + |
| 93 | +Use the following faucets to get testnet native tokens in your wallets: |
| 94 | + |
| 95 | +* [Ethereum Sepolia faucet](https://sepoliafaucet.com) |
| 96 | +* [Base Sepolia faucet](https://www.alchemy.com/faucets/base-sepolia) |
| 97 | + |
| 98 | +:::tip |
| 99 | +Instead of using the Base Sepolia faucet, you can use the Ethereum Sepolia faucet to transfer some tokens to Base. |
| 100 | +::: |
| 101 | + |
| 102 | +### Create the transfer script |
| 103 | + |
| 104 | +Create an `index.ts` file in the project directory and add the following code. This code sets up your script and transfers 10 USDC from Base to Ethereum: |
| 105 | + |
| 106 | +```ts [index.ts] |
| 107 | +// Import Bridge Kit and its dependencies |
| 108 | +import "dotenv/config"; |
| 109 | +import { BridgeKit } from "@circle-fin/bridge-kit"; |
| 110 | +import { createAdapterFromPrivateKey } from "@circle-fin/adapter-viem-v2"; |
| 111 | +import { inspect } from "util"; |
| 112 | + |
| 113 | +// Initialize the SDK |
| 114 | +const kit = new BridgeKit(); |
| 115 | + |
| 116 | +const bridgeUSDC = async (): Promise<void> => { |
| 117 | + try { |
| 118 | + // Initialize the adapter which lets you transfer tokens from your wallet on any EVM-compatible chain |
| 119 | + const adapter = createAdapterFromPrivateKey({ |
| 120 | + privateKey: process.env.PRIVATE_KEY as string, |
| 121 | + }); |
| 122 | + |
| 123 | + console.log("---------------Starting Bridging---------------"); |
| 124 | + |
| 125 | + // Execute the transfer using the same adapter for both source and destination chain |
| 126 | + const result = await kit.bridge({ |
| 127 | + from: { adapter, chain: "Base_Sepolia" }, |
| 128 | + to: { adapter, chain: "Ethereum_Sepolia" }, |
| 129 | + amount: "10", |
| 130 | + }); |
| 131 | + |
| 132 | + console.log("RESULT", inspect(result, false, null, true)); |
| 133 | + } catch (err) { |
| 134 | + console.log("ERROR", inspect(err, false, null, true)); |
| 135 | + } |
| 136 | +}; |
| 137 | + |
| 138 | +void bridgeUSDC(); |
| 139 | +``` |
| 140 | + |
| 141 | +### Run the transfer |
| 142 | + |
| 143 | +Save the `index.ts` file and run the script in your terminal: |
| 144 | + |
| 145 | +```bash |
| 146 | +npx tsx index.ts |
| 147 | +``` |
| 148 | + |
| 149 | +### Verify the transfer |
| 150 | + |
| 151 | +After your script completes, find the returned `steps` array in the terminal output. Each transaction step includes an `explorerUrl` that you can visit to verify that the USDC amount matches the amount you transferred. |
| 152 | + |
| 153 | +The following code is an example of how an `approve` step might look in the terminal output. The values are used in this example only and are not a real transaction: |
| 154 | + |
| 155 | +```bash |
| 156 | +steps: [ |
| 157 | + { |
| 158 | + name: "approve", |
| 159 | + state: "success", |
| 160 | + txHash: "0x...txHash", |
| 161 | + data: { |
| 162 | + txHash: |
| 163 | + "0x...txHash", |
| 164 | + status: "success", |
| 165 | + cumulativeGasUsed: 24567891n, |
| 166 | + gasUsed: 52843n, |
| 167 | + blockNumber: 8921456n, |
| 168 | + blockHash: |
| 169 | + "0x...blockHash", |
| 170 | + transactionIndex: 245, |
| 171 | + effectiveGasPrice: 1523456n, |
| 172 | + explorerUrl: |
| 173 | + "https://sepolia.etherscan.io/tx/0x...txHash", |
| 174 | + }, |
| 175 | + }, |
| 176 | +] |
| 177 | +``` |
| 178 | + |
| 179 | +:::tip |
| 180 | +[Collect a fee on transfers](https://learn.circle.com/bridge-kit/tutorials/collect-a-transfer-fee) and [estimate gas and provider fees](https://learn.circle.com/bridge-kit/tutorials/estimate-costs) before a transfer, only proceeding if the cost is acceptable. |
| 181 | +::: |
| 182 | + |
| 183 | +:::: |
0 commit comments