@circle-fin/bridge-kit

中文文档
1.17.1发布于 2026/11/06TypeScriptESM + CJS近 30 天下载 5.6万

Official Circle SDK for seamless cross-chain USDC bridging

原始使用文档
文档目录42 节
  1. Table of Contents
  2. Overview
  3. Why Bridge Kit?
  4. Developer Documentation
  5. Architecture Flow
  6. Installation
  7. Adapters
  8. Quick Start
  9. 🚀 Easiest Setup: Single Adapter, Multiple Chains
  10. 🎯 Send to Different Address
  11. 🏭 Production Setup: Custom RPC Providers
  12. 🌐 Browser/Wallet Provider Support
  13. 🔧 Advanced Setup: Full Control
  14. 📊 Cost Estimation
  15. Configuration
  16. Bridge Configuration Types
  17. Bridge Speed Configuration
  18. Custom Fees
  19. How Custom Fees Work
  20. 1,000 USDC Transfer Example
  21. Kit-Level Fee Policies
  22. Error Handling
  23. Retrying Failed Transfers
  24. Method signature
  25. Basic usage (EVM → EVM)
  26. When to retry vs manual intervention
  27. Limitations
  28. Performance and best practices
  29. Troubleshooting
  30. Forwarder Integration
  31. Standard Bridge with Forwarder
  32. Forwarder-Only Destination (No Destination Adapter)
  33. Receive-exact forwarding with source-paid fees
  34. API Reference
  35. Core Methods
  36. Bridge Parameters
  37. Development
  38. Building
  39. Testing
  40. Local Development
  41. Community & Support
  42. License

Bridge Kit

npm version TypeScript License Discord

Official Circle SDK for seamless cross-chain USDC bridging

Bridge Kit is the recommended integration surface for USDC bridging between EVM and non-EVM chains, making bridging as simple as a single function call

Table of Contents

Overview

The App Kit ecosystem is Circle’s open-source effort to streamline stablecoin development with SDKs that are easy to use correctly and hard to misuse. Kits are cross-framework (viem, ethers, @solana/web3) and integrate cleanly into any stack. They’re opinionated with sensible defaults, but offer escape hatches for full control. A pluggable architecture makes implementation flexible, and all kits are interoperable, so they can be composed to suit a wide range of use cases.

The Bridge Kit enables cross-chain stablecoin transfers via a type-safe, developer-friendly interface with robust runtime validation. The Kit can have any bridging provider plugged in, by implementing your own BridgingProvider, but comes by default with full CCTPv2 support

Why Bridge Kit?

  • 🌉 Bridge-first design: All abstractions revolve around source ↔ destination chain pairs
  • ⚡ Zero-config defaults: Built-in reliable RPC endpoints - start building right away
  • 🔧 Bring your own infrastructure: Seamlessly integrate with your existing setup when needed
  • 🔒 Production-ready security: Leverages Circle's CCTPv2 with deterministic quotes and finality tracking
  • 🚀 Developer experience: Complete TypeScript support, comprehensive validation, and instant connectivity
  • 🌍 Cross-chain bridging: The Bridge Kit supports 52 chains with 1300 total bridge routes through Circle's CCTPv2
    • Mainnet (26 chains): Arbitrum, Arc, Avalanche, Base, Codex, Cronos, Edge, Ethereum, HyperEVM, Injective, Ink, Linea, Monad, Morph, OP Mainnet, Pharos, Plasma, Plume, Polygon PoS, Sei, Solana, Sonic, Unichain, World Chain, XDC, X Layer
    • Testnet (26 chains): Arc Testnet, Arbitrum Sepolia, Avalanche Fuji, Base Sepolia, Codex Testnet, Cronos Testnet, Edge Testnet, Ethereum Sepolia, HyperEVM Testnet, Injective Testnet, Ink Testnet, Linea Sepolia, Monad Testnet, Morph Testnet, OP Sepolia, Pharos Atlantic, Plasma Testnet, Plume Testnet, Polygon PoS Amoy, Sei Testnet, Solana Devnet, Sonic Testnet, Unichain Sepolia, World Chain Sepolia, XDC Apothem, X Layer Testnet
  • 🎯 Flexible adapters: Supporting EVM (Viem, Ethers) and Solana (@solana/web3)
  • ⚙️ Configurable bridge speeds: FAST/SLOW options with fee optimization
  • 📡 Real-time event monitoring: Track progress throughout the transfer lifecycle
  • 🛡️ Robust error handling: Graceful partial success recovery
  • ✈️ Pre-flight validation: Verify transfers with cost estimation before execution
  • 🤖 Forwarder integration: Circle's Orbit relayer handles attestation and mint automatically
  • 📭 Forwarder-only destinations: No destination adapter required - just provide recipient address

Developer Documentation

Architecture Flow

The Bridge Kit follows a three-layer architecture designed for flexibility and type safety:

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│   Bridge Kit    │────│     Provider     │────│   Adapter       │
│  (Orchestrator) │    │   (Protocol)     │    │ (Blockchain)    │
└─────────────────┘    └──────────────────┘    └─────────────────┘
  1. Adapter: Handles blockchain-specific operations (wallets, transactions, gas) and enables you to use whatever framework you're comfortable with (viem, ethers, @solana/web3, and more coming soon)
  2. Provider: Implements bridging protocols (currently CCTPv2)
  3. BridgeKit: Orchestrates adapters and providers with auto-routing and validation

This separation ensures that each component has a single responsibility while maintaining seamless integration across the entire cross-chain bridging lifecycle.

Installation

npm install @circle-fin/bridge-kit
# or
yarn add @circle-fin/bridge-kit

Adapters

Choose the appropriate adapter for your target chains:

# For EVM chains (Ethereum, Base, Arbitrum, etc.)
npm install @circle-fin/adapter-viem-v2 viem
# or
yarn add @circle-fin/adapter-viem-v2 viem

# For EVM chains using Ethers.js
npm install @circle-fin/adapter-ethers-v6
# or
yarn add @circle-fin/adapter-ethers-v6

# For Solana
npm install @circle-fin/adapter-solana @solana/web3.js
# or
yarn add @circle-fin/adapter-solana @solana/web3.js

Quick Start

🚀 Easiest Setup: Single Adapter, Multiple Chains

Best for: Getting started quickly, simple transfers using one wallet across chains

The factory methods make it incredibly easy to get started with built-in reliable RPC endpoints. No need to research providers or configure endpoints - just start building! Create one adapter and use it across different chains!

import { BridgeKit } from '@circle-fin/bridge-kit'
import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'

// Initialize the kit
const kit = new BridgeKit()

// Create ONE adapter that works across all chains!
const adapter = createViemAdapterFromPrivateKey({
  privateKey: process.env.PRIVATE_KEY as string,
})

const result = await kit.bridge({
  from: { adapter, chain: 'Ethereum' },
  to: { adapter, chain: 'Base' },
  amount: '10.50',
})

✨ Key Feature: All supported chains include reliable default RPC endpoints.

🎯 Send to Different Address

Best for: Sending funds to someone else's wallet, custodial services

Use BridgeDestinationWithAddress when the recipient is different from your adapter's address:

// Send to a different address on the destination chain
const result = await kit.bridge({
  from: { adapter, chain: 'Ethereum' },
  to: {
    adapter,
    chain: 'Base',
    recipientAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  },
  amount: '10.50',
})

// Or use a different adapter for the destination chain
const baseAdapter = createViemAdapterFromPrivateKey({
  privateKey: process.env.PRIVATE_KEY as string,
})

const resultWithDifferentAdapter = await kit.bridge({
  from: { adapter, chain: 'Ethereum' },
  to: {
    adapter: baseAdapter,
    chain: 'Base',
    recipientAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  },
  amount: '10.50',
})

🏭 Production Setup: Custom RPC Providers

Best for: Production applications, better reliability, custom configuration

Bridging involves two chains (source and destination), and both require properly configured RPC endpoints. Use dynamic RPC mapping by chain ID to support multiple chains in a single adapter:

import 'dotenv/config'
import { BridgeKit } from '@circle-fin/bridge-kit'
import { Ethereum, Base } from '@circle-fin/bridge-kit/chains'
import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
import { createPublicClient, http, fallback } from 'viem'

// Define RPCs mapped by chain ID
const RPC_BY_CHAIN_ID: Record<number, string[]> = {
  // The array allows providing multiple RPC URLs for fallback, e.g.,
  // `[ "https://primary-rpc-url.com/...", "https://secondary-rpc-url.com/..." ]`
  [Ethereum.chainId]: [
    `https://eth-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_KEY}`,
  ],
  [Base.chainId]: [
    `https://base-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_KEY}`,
  ],
}

const adapter = createViemAdapterFromPrivateKey({
  privateKey: process.env.PRIVATE_KEY as `0x${string}`,
  getPublicClient: ({ chain }) => {
    const rpcUrls = RPC_BY_CHAIN_ID[chain.id]
    if (!rpcUrls) {
      throw new Error(`No RPC configured for chainId=${chain.id}`)
    }
    return createPublicClient({
      chain,
      transport: fallback(
        rpcUrls.map((url) =>
          http(url, {
            timeout: 10_000,
            retryCount: 3,
          }),
        ),
      ),
    })
  },
})

const kit = new BridgeKit()

const result = await kit.bridge({
  from: { adapter, chain: 'Ethereum' },
  to: { adapter, chain: 'Base' },
  amount: '10.50',
})

Best practices:

  • Use paid RPC providers (Alchemy, Infura, QuickNode) for improved reliability
  • Implement fallback() transport for automatic failover between endpoints
  • Configure timeout and retry options to handle network variability

🌐 Browser/Wallet Provider Support

Best for: Browser applications, wallet integrations, user-controlled transactions

import { BridgeKit } from '@circle-fin/bridge-kit'
import { createViemAdapterFromProvider } from '@circle-fin/adapter-viem-v2'

const kit = new BridgeKit()

// Create adapters from browser wallet providers
const adapter = await createViemAdapterFromProvider({
  provider: window.ethereum,
})

// Execute bridge operation
const result = await kit.bridge({
  from: { adapter, chain: 'Ethereum' },
  to: { adapter, chain: 'Base' },
  amount: '10.50',
})

🔧 Advanced Setup: Full Control

Best for: Advanced users, custom client configuration, specific RPC requirements

import { BridgeKit } from '@circle-fin/bridge-kit'
import { Ethereum, Base } from '@circle-fin/bridge-kit/chains'
import { ViemAdapter } from '@circle-fin/adapter-viem-v2'
import { createPublicClient, createWalletClient, http } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'

const account = privateKeyToAccount(process.env.PRIVATE_KEY as string)

// Chain-specific RPC URLs mapped by chain ID
const rpcUrls: Record<number, string> = {
  [Ethereum.chainId]: 'https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY',
  [Base.chainId]: 'https://base-mainnet.g.alchemy.com/v2/YOUR_KEY',
}

// Create one multi-chain adapter with chain-specific RPC configuration
const adapter = new ViemAdapter(
  {
    getPublicClient: ({ chain }) =>
      createPublicClient({
        chain,
        transport: http(rpcUrls[chain.id]),
      }),
    getWalletClient: ({ chain }) =>
      createWalletClient({
        account,
        chain,
        transport: http(rpcUrls[chain.id]),
      }),
  },
  {
    addressContext: 'user-controlled',
    supportedChains: [Ethereum, Base], // Support multiple chains!
  },
)

const kit = new BridgeKit()
// Execute bridge operation using the same adapter for both chains
const result = await kit.bridge({
  from: { adapter, chain: 'Ethereum' },
  to: { adapter, chain: 'Base' },
  amount: '10.50',
})

📊 Cost Estimation

Best for: Showing users fees upfront, budget planning

// Get cost estimate before bridging
const estimate = await kit.estimate({
  from: { adapter, chain: 'Ethereum' },
  to: { adapter, chain: 'Base' },
  amount: '10.50',
})

console.log('Estimated fees:', estimate.fees)
console.log('Estimated gas:', estimate.gasFees)

Configuration

Bridge Configuration Types

The Bridge Kit supports different configuration patterns to match your use case:

1. AdapterContext - Your Transfer Endpoint

// Create chain-agnostic adapter
const adapter = createViemAdapterFromPrivateKey({...})

// Always specify chain explicitly for clarity
const adapterContext = { adapter, chain: 'Ethereum' }

2. BridgeDestination - Where Funds Go

// Same as AdapterContext (adapter receives the funds)
const destination = { adapter, chain: 'Base' }

// Or with explicit recipient address
const destination = {
  adapter,
  chain: 'Base',
  recipientAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
}

3. BridgeConfig - Transfer Settings

// FAST: Optimized for speed with higher fees
// SLOW: Optimized for lower fees with longer processing time
const config = { transferSpeed: 'FAST' }

Bridge Speed Configuration

// Fast transfer (higher fees, faster completion)
const result = await kit.bridge({
  from: { adapter, chain: 'Ethereum' },
  to: { adapter, chain: 'Base' },
  amount: '100.0',
  config: { transferSpeed: 'FAST' },
})

// Slow transfer (lower fees, slower completion)
const result = await kit.bridge({
  from: { adapter, chain: 'Ethereum' },
  to: { adapter, chain: 'Base' },
  amount: '100.0',
  config: { transferSpeed: 'SLOW' },
})

Custom Fees

Bridge Kit allows you to charge custom developer fees on cross-chain USDC transfers. Understanding how these fees interact with wallet debits and CCTPv2 protocol fees is crucial for correct implementation.

How Custom Fees Work

Custom fees are added on top of the transfer amount, not taken out of it. The wallet signs for transfer amount + custom fee, so the user must have enough balance for both values. The entire transfer amount continues through CCTPv2 unchanged, while the custom fee is split on the source chain:

  • 10% of the custom fee is automatically routed to Circle.
  • 90% is sent to your recipientAddress.
  • Important: Circle only takes the 10% share when a custom fee is actually charged. If you omit a custom fee, Circle does not collect anything beyond the protocol fee.

After the custom fee is collected, the transfer amount (e.g., 1,000 USDC) proceeds through CCTPv2, where the protocol applies its own fee (1–14 bps in FAST mode, 0% in STANDARD).

Fee Flow (1,000 USDC transfer + 10 USDC custom fee):

┌───────────────────────────────────────────────────────────────┐
│ User signs: 1,000 USDC transfer + 10 USDC custom fee = 1,010  │
└──────────────────────┬────────────────────────────────────────┘
                       │
                       ▼
┌───────────────────────────────────────────────────────────────┐
│ Custom fee distribution (source chain)                        │
│  - 1 USDC (10%) → Circle                                      │
│  - 9 USDC (90%) → Your fee recipient                          │
└──────────────────────┬────────────────────────────────────────┘
                       │
                       ▼
┌───────────────────────────────────────────────────────────────┐
│ CCTPv2 processes full transfer amount (1,000 USDC)            │
│  - Protocol fee example (FAST 1 bps): 0.1 USDC                │
│  - Destination receives: 999.9 USDC                           │
└───────────────────────────────────────────────────────────────┘

1,000 USDC Transfer Example

Scenario: Transfer 1,000 USDC from Ethereum to Base with a 10 USDC custom fee.

import { BridgeKit } from '@circle-fin/bridge-kit'
import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'

const kit = new BridgeKit()
const adapter = createViemAdapterFromPrivateKey({
  privateKey: process.env.PRIVATE_KEY as `0x${string}`,
})

await kit.bridge({
  from: { adapter, chain: 'Ethereum' },
  to: { adapter, chain: 'Base' },
  amount: '1000', // Transfer amount forwarded to CCTPv2
  config: {
    customFee: {
      value: '10', // Additional debit charged on top of the transfer amount
      recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0',
    },
  },
})

What happens on-chain:

StageAmountDescription
Transfer amount1,000 USDCForwarded to CCTPv2 without reduction
Custom fee debit+10 USDCWallet signs for 1,010 USDC total
Custom fee → Circle (10%)1 USDCAutomatically routed to Circle
Custom fee → You (90%)9 USDCSent to 0x742d35Cc...bEb0 (your fee recipient)
CCTPv2 fee (FAST 1 bps)*-0.1 USDCProtocol fee taken from the 1,000 USDC transfer amount
Destination receives999.9 USDCAmount minted on Base after protocol fee

* _CCTPv2 FAST transfers charge 1–14 bps depending on the route; STANDARD transfers charge 0 bps.

Kit-Level Fee Policies

For dynamic fee calculation across all transfers, use kit-level policies:

import { BridgeKit } from '@circle-fin/bridge-kit'
import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'

const kit = new BridgeKit()
const adapter = createViemAdapterFromPrivateKey({
  privateKey: process.env.PRIVATE_KEY as `0x${string}`,
})

kit.setCustomFeePolicy({
  computeFee: (params) => {
    const amount = parseFloat(params.amount)

    const feePercentage = 0.01 // 1%
    const calculatedFee = amount * feePercentage

    // Return human-readable fee (e.g., '10' for 10 USDC)
    return calculatedFee.toFixed(6)
  },
  resolveFeeRecipientAddress: (feePayoutChain) => {
    // Return appropriate address for source chain
    return feePayoutChain.type === 'solana'
      ? 'SolanaAddressBase58...'
      : '0xEvmAddress...'
  },
})

// All subsequent bridges will use this policy
await kit.bridge({
  from: { adapter, chain: 'Ethereum' },
  to: { adapter, chain: 'Base' },
  amount: '1000', // Custom fee calculated automatically
})

Note: The calculateFee function is deprecated. Use computeFee instead, which receives human-readable amounts (e.g., '100' for 100 USDC) rather than smallest-unit amounts.

Error Handling

The kit uses a thoughtful error handling approach:

  • Hard errors (thrown): Validation, configuration, and authentication errors
  • Soft errors (returned): Recoverable issues like insufficient balance or network errors
import { BridgeKit } from '@circle-fin/bridge-kit'
import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'

const kit = new BridgeKit()
const adapter = createViemAdapterFromPrivateKey({
  privateKey: process.env.PRIVATE_KEY as string,
})

const params = {
  from: { adapter, chain: 'Ethereum' },
  to: { adapter, chain: 'Base' },
  amount: '100.0',
}

const result = await kit.bridge(params)

if (result.state === 'success') {
  console.log('Bridge successful!')
} else {
  // Handle partial completion with recovery information
  console.log(
    'Successful steps:',
    result.steps.filter((s) => s.state === 'success'),
  )
}

Retrying Failed Transfers

Use BridgeKit.retry to resume failed or incomplete bridge operations when the failure is actionable (e.g., transient RPC issues, dropped transactions, or a failed step in a multi-step flow). The kit delegates retry to the original provider (CCTPv2 supports actionable retries) and continues from the appropriate step.

Method signature

retry<
  TFromAdapterCapabilities extends AdapterCapabilities,
  TToAdapterCapabilities extends AdapterCapabilities
>(
  result: BridgeResult,
  context: RetryContext<TFromAdapterCapabilities, TToAdapterCapabilities>
): Promise<BridgeResult>

Basic usage (EVM → EVM)

import { BridgeKit } from '@circle-fin/bridge-kit'
import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'

const kit = new BridgeKit()
const adapter = createViemAdapterFromPrivateKey({
  privateKey: process.env.PRIVATE_KEY as `0x${string}`,
})

const result = await kit.bridge({
  from: { adapter, chain: 'Ethereum_Sepolia' },
  to: { adapter, chain: 'Base_Sepolia' },
  amount: '1',
})

if (result.state === 'error') {
  try {
    const retryResult = await kit.retry(result, { from: adapter, to: adapter })
    console.log('Retry state:', retryResult.state)
  } catch (error) {
    console.error('Retry failed:', error)
  }
}

When to retry vs manual intervention

  • Retry: transient network/RPC errors, gas repricing/dropped txs, step failure with progress recorded.
  • Manual: insufficient funds, incorrect recipient, unsupported route, or errors indicating non-actionable state.

Limitations

  • Only actionable failures can be retried; some failures require user action first.
  • Source and destination chains must still be supported by the provider (CCTPv2).
  • Provide valid adapters for both from and to contexts.

Performance and best practices

  • Use exponential backoff on transient failures; avoid rapid replay.
  • Reprice gas sensibly on congested networks.
  • Persist result.steps and tx hashes to aid observability and support.

Troubleshooting

  • "Retry not supported for this result, requires user action": fix balances/addresses/attestation issues and try again.
  • "Provider not found": ensure the same provider (e.g., CCTPv2) is present in BridgeKit configuration.

See a runnable example at examples/basic-usdc-transfer/src/retry.ts (script: yarn start:retry).

Forwarder Integration

The Bridge Kit supports Circle's Orbit relayer for automated attestation and mint handling. When enabled, the relayer automatically fetches the attestation and submits the mint transaction on the destination chain, simplifying the bridging process.

Standard Bridge with Forwarder

Use useForwarder: true when you have adapters for both chains but want Circle to handle the mint transaction:

import { BridgeKit } from '@circle-fin/bridge-kit'
import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'

const kit = new BridgeKit()
const adapter = createViemAdapterFromPrivateKey({
  privateKey: process.env.PRIVATE_KEY as `0x${string}`,
})

const result = await kit.bridge({
  from: { adapter, chain: 'Ethereum' },
  to: {
    adapter,
    chain: 'Base',
    useForwarder: true, // Circle handles attestation + mint
  },
  amount: '100.50',
})

Benefits:

  • No manual attestation polling or destination mint submission
  • Relayer handles destination mint transaction automatically
  • Simplified flow with fewer client-side operations

Forwarder-Only Destination (No Destination Adapter)

When you don't have access to a wallet on the destination chain, use forwarder-only mode. This is ideal for server-side transfers, custodial services, or when users don't have a wallet on the destination chain:

const result = await kit.bridge({
  from: { adapter, chain: 'Ethereum' },
  to: {
    recipientAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', // Recipient on destination
    chain: 'Base',
    useForwarder: true, // Required for forwarder-only
  },
  amount: '100.50',
})

Key differences from standard bridging:

  • No destination adapter required
  • Mint confirmation is based on IRIS API response (not on-chain receipt)
  • Mint step's data field will be undefined

Relay fee handling:

  • Relay fee is automatically included in maxFee estimate
  • Fee is deducted from the minted USDC at mint time
  • Net received = burn amount - relay fee
// Estimate includes relay fee when forwarder is enabled
const estimate = await kit.estimate({
  from: { adapter, chain: 'Ethereum' },
  to: {
    recipientAddress: '0x...',
    chain: 'Base',
    useForwarder: true,
  },
  amount: '100.50',
})

console.log(estimate.maxFee) // Includes both burn fee and relay fee

If you provide config.maxFee manually, include forwarder fees yourself. Auto-inclusion applies when the kit computes fees from route/speed. For Solana destinations, the forwarder fee also covers creating the recipient's USDC token account.

You can discover forwarder-capable chains with kit.getSupportedChains({ forwarderSupported: true }).

See runnable examples at examples/basic-usdc-transfer/src/forwarder-*.ts.

Receive-exact forwarding with source-paid fees

Opt in with config.feePayment: 'source' when the recipient must receive the exact requested amount. Bridge Kit obtains a short-lived signed Fee Service quote, approves amount + feeTotal in source-chain USDC, and burns exactly amount through TokenMessengerWithFees. The destination mint is not reduced.

useForwarder: true remains required. Omitting feePayment preserves the existing destination-paid behavior.

const params = {
  from: { adapter, chain: 'Ethereum' },
  to: {
    chain: 'Base',
    recipientAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
    useForwarder: true,
  },
  amount: '100',
  config: {
    transferSpeed: 'FAST',
    feePayment: 'source',
  },
} as const

const estimate = await kit.estimate(params)
if ('amountReceived' in estimate) {
  console.log('Recipient receives:', estimate.amountReceived) // 100 USDC
  console.log('Source wallet pays:', estimate.totalDebit) // e.g. 100.42 USDC
  console.log('Quote expires:', estimate.quoteExpiry)

  const result = await kit.bridge({
    ...params,
    quote: estimate.quote,
  })
  console.log(result.state)
}

Treat quote as opaque and never log it. Bridge Kit validates a supplied quote against the exact transfer parameters before approval and again immediately before burning. If it is invalid, mismatched, expired, or too close to expiry, the bridge fails and you must estimate again. Omit quote to let Bridge Kit fetch a fresh quote automatically.

The initial release supports EVM sources, EVM destinations, and source-chain USDC fee payment. Custom developer fees are not supported in this mode. On a 429 response, retry the estimate or bridge call with caller-managed exponential backoff. 503 SERVICE_NOT_ENABLED means the source route is disabled and should not be retried.

API Reference

Core Methods

  • kit.bridge(params) - Execute cross-chain bridge operation
  • kit.estimate(params) - Get cost estimates before bridging
  • kit.retry(result, context) - Resume actionable failed/partial transfers
  • kit.getSupportedChains(options?) - Query supported chains with optional filters
  • kit.setCustomFeePolicy(policy) - Set a dynamic custom fee policy
  • kit.removeCustomFeePolicy() - Remove the configured custom fee policy
  • kit.on(event, handler) - Listen to bridge events
  • kit.off(event, handler) - Removes the listener from bridge events

bridge and estimate are not limited to USDC. Omitting token (or passing 'USDC') bridges USDC via CCTP v2; passing a non-USDC symbol such as cirBTC, wETH or EURC, or a bytes32 0x… token id, bridges that token via CCTPx. See Bridge Parameters for the accepted forms.

Bridge Parameters

interface BridgeParams {
  from: AdapterContext // Source wallet and chain
  to: BridgeDestination // Destination wallet/address and chain
  amount: string // Amount to transfer (e.g., '10.50')
  token?: BridgeToken // 'USDC', a known CCTPx symbol, or a bytes32 token id
  config?: BridgeConfig // Optional bridge configuration (e.g., transfer speed). If omitted, defaults will be used
}

type BridgeToken =
  | 'USDC'
  | 'cirBTC'
  | 'wETH'
  | 'EURC'
  | `0x${string}` // runtime: 0x + exactly 64 hex characters

// AdapterContext: Your blockchain connection
type AdapterContext = {
  adapter: Adapter
  chain: ChainIdentifier
  address?: string // Required for developer-controlled adapters; forbidden for user-controlled
}

// BridgeDestination: Where funds go
type BridgeDestination =
  | AdapterContext
  | {
      adapter: Adapter // Adapter for the destination chain
      chain: ChainIdentifier // Chain identifier
      recipientAddress?: string // Custom recipient address
      useForwarder?: boolean // Enable Circle's Orbit relayer
    }
  | {
      // Forwarder-only destination (no adapter required)
      recipientAddress: string // Required: where to receive USDC
      chain: ChainIdentifier // Chain identifier
      useForwarder: true // Required: must be true
    }

Development

Building

# From the root of the monorepo
nx build @circle-fin/bridge-kit

Testing

# From the root of the monorepo
nx test @circle-fin/bridge-kit

Local Development

# Install dependencies
yarn install

# Build all packages
yarn build

# Build the bridge-kit specifically
nx build @circle-fin/bridge-kit

# Run tests
nx test @circle-fin/bridge-kit

Community & Support

License

This project is licensed under the Apache 2.0 License. Contact support for details.


Ready to start bridging?

Join Discord

Built with ❤️ by Circle

版本与发布记录

@circle-fin/bridge-kit 共发布 35 个版本,首次发布于 2025/10/14;过去 12 个月发布了 32 个版本。

版本发布日期距今
1.17.1latest2026/11/063 天前
1.17.02026/10/3110 天前
1.16.12026/10/2317 天前
1.16.02026/10/2119 天前
1.15.32026/10/1624 天前
1.15.22026/09/301 个月前

关于 @circle-fin/bridge-kit 的常见问题

@circle-fin/bridge-kit 是什么?

Official Circle SDK for seamless cross-chain USDC bridging

如何安装 @circle-fin/bridge-kit?

在项目目录运行 npm install @circle-fin/bridge-kit,或使用 pnpm add / yarn add / bun add。

@circle-fin/bridge-kit 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@circle-fin/bridge-kit 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@circle-fin/bridge-kit 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@circle-fin/bridge-kit 可以商用吗?

@circle-fin/bridge-kit 使用 未声明 许可。package.json 没有声明许可证。没有许可证的代码默认保留全部权利,商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括,不构成法律意见,请以许可原文为准。

@circle-fin/bridge-kit 的下载量有多少?

根据 npm 官方下载统计,@circle-fin/bridge-kit 在 2026/10/10 – 2026/11/08 这 30 天内被下载 55,736 次,日均约 1,858 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@circle-fin/bridge-kit 还在维护吗?

最新版本 1.17.1 发布于 2026/11/06(3 天前);至今共发布 35 个版本,其中过去 12 个月发布了 32 个;首次发布于 2025/10/14。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。