Build an embedded USDC transfer surface that lets a connected wallet send USDC on one chain or bridge USDC across chains through App Kit.
This React + Vite project demonstrates a practical transfer flow for apps that want to hide low-level routing decisions from users. The widget discovers a browser wallet, creates the right Circle adapter, estimates the route, and then uses:
send()for same-chain USDC transfersbridge()for crosschain USDC transfers through either CCTP Forwarder or direct mint routesretryBridge()when a bridge attempt returns an error state
The entered amount is treated as the amount the recipient should receive. For a crosschain bridge, the review screen also shows the estimated total source cost.
- A wallet connection flow for injected EVM wallets and Solana browser wallets
- App Kit adapter creation from the connected browser wallet
- Chain options derived from App Kit support rather than hardcoded lists
- Same-chain USDC transfer execution with
send() - Crosschain USDC bridge execution through CCTP Forwarder or direct mint routes
- Transfer review that shows destination amount, estimated fee, total source amount, recipient, and method
- Basic bridge retry handling for recoverable bridge error states
Connect wallet
-> create Circle adapter
-> choose source chain, destination chain, recipient, and amount
-> estimate transfer
-> review amount and fees
-> sign and submit
-> show explorer links for completed steps
The widget chooses the transfer method from the selected route:
| Route | App Kit method | Behavior |
|---|---|---|
| Same source and destination chain | send() |
Transfers USDC on the connected chain. |
| Different source and destination chains, destination supports Forwarder | bridge() with useForwarder: true |
Bridges USDC crosschain and sends to the entered recipient address. |
| Different source and destination chains, EVM direct mint route | bridge() with a destination adapter |
Bridges USDC crosschain using the connected EVM wallet as the destination adapter. |
- Node.js v22+
- A supported injected EVM wallet, Solana browser wallet, or both
- EVM wallet discovery uses EIP-6963 provider announcements.
- Solana wallet detection expects a browser wallet on
window.solana.
- Testnet USDC on the source chain you want to use
- Native gas token on the source chain for the wallet transaction
- Familiarity with App Kit
This project does not require environment variables or API keys.
Install dependencies:
npm installStart the development server:
npm run devOpen the local Vite URL in a browser with a supported wallet installed.
Build the production bundle:
npm run build- Connect an EVM or Solana wallet.
- Select a source chain supported by the connected wallet type.
- Select a destination chain.
- Enter a recipient address.
- Enter the USDC amount the recipient should receive.
- Review the estimated fee and total source amount.
- Confirm and sign in your wallet.
For crosschain bridges, the widget sends the entered amount to bridge() and
shows the entered amount plus estimated USDC bridge fees as the total source
amount during review.
When the transfer completes, the widget shows explorer links for any App Kit steps that returned an explorer URL.
src/
components/
TransferWidget/
TransferWidget.tsx # UI state, screens, and user actions
transfer.ts # App Kit setup, estimation, send, bridge, retry
wallet.ts # Wallet discovery, connection, adapter creation
TransferWidget.css
index.ts
main.tsx # App entry and widget mount
index.css
src/components/TransferWidget/wallet.tsdiscovers EIP-6963 EVM wallets, detects Solana wallets, connects the selected wallet, and creates the matching Circle adapter.src/components/TransferWidget/transfer.tscreates the App Kit instance, fetches supported testnet chains, estimates send and bridge routes, executes transfers, and retries bridge flows when needed.src/components/TransferWidget/TransferWidget.tsxowns the widget screens: connect, wallet selection, transfer form, review, submitting, and success.
This repository is a runnable app, not a packaged component library. If you copy
src/components/TransferWidget/ into another React app, also install the runtime
dependencies below.
The copied widget expects these runtime dependencies:
@circle-fin/app-kit@circle-fin/adapter-viem-v2@circle-fin/adapter-solana@solana/web3.jsreactreact-domviem
| Command | What it does |
|---|---|
npm run dev |
Starts the local Vite development server. |
npm run build |
Runs TypeScript and creates a production build. |
npm run lint |
Runs ESLint. |
npm run preview |
Serves the production build locally. |
Before adapting this pattern for a live app:
- Validate recipient addresses for the selected destination chain.
- Handle unsupported wallet, chain, and route states explicitly.
- Decide whether to support only testnets, only mainnets, or both.
- Add stronger transaction status handling and user-facing recovery paths.
- Persist transfer attempts if users may close the browser mid-flow.
- Keep route support derived from App Kit where possible so chain support does not drift from the SDK.
This repository does not currently publish a stable package API, package exports, or a library build.