# @circle-fin/bridge-kit

## 1.15.1

### Patch Changes

- Fix CORS errors that blocked CCTPX fee-quote requests from browser-based clients.

## 1.15.0

### Minor Changes

- Add Arc mainnet (`Blockchain.Arc`, chainId 5042) as a supported chain. Arc is wired for CCTP v2 bridging (`BridgeChain.Arc`, domain 26) with Circle's Forwarding Service enabled for Arc as a destination, and for Gateway v1 (`UnifiedBalanceChain.Arc`).
- Make Arc mainnet a CCTPx endpoint

  Arc mainnet's chain definition gains `cctpx.serviceAddress`, pointing at the mainnet
  CrossChainTokenService. `isCCTPXSupported(Chains.Arc)` becomes `true`, so Arc joins the
  chains reported by `CCTPXBridgingProvider.getSupportedChains()`, and by Bridge Kit and App
  Kit through it.

  A chain being eligible does not by itself make a route usable: the token registry must list
  the token with a deployment on both endpoints' CCTP domains.

- Bridge EURC between Base and Ethereum mainnet

  Bridge Kit now supports EURC transfers between Base and Ethereum mainnet through Circle's CCTPx protocol. Pass `EURC` as `token` on `bridge` and `estimate`:

  ```ts
  import { BridgeKit } from "@circle-fin/bridge-kit";

  const kit = new BridgeKit();

  const result = await kit.bridge({
    token: "EURC",
    from: { adapter, chain: "Base" },
    to: { adapter, chain: "Ethereum" },
    amount: "100",
  });
  ```

  CCTPx also supports `cirBTC`, `wETH`, `EURC`, and raw `bytes32` token ids on eligible testnet routes.

  - Routed results support provider-defined token identifiers while bare `BridgeResult` and `EstimateResult` types remain USDC-specific for source compatibility.
  - `bridge` and `estimate` reject custom fees on non-USDC routes. CCTPx routes accept `feePayment` only when omitted or set to `'source'`, and `useForwarder` only when omitted or set to `true`.
  - Route discovery continues to other providers when one provider's route check fails. If no provider supports the route, Bridge Kit preserves retryable failures on the resulting error.

- Enable CCTPx on Arbitrum, Avalanche, Optimism and Polygon mainnet

  These four chain definitions gain `cctpx.serviceAddress`, pointing at the mainnet
  CrossChainTokenService. They join Ethereum and Base in the chains reported by
  `CCTPXBridgingProvider.getSupportedChains()`, and by Bridge Kit and App Kit through it.

  A chain being eligible does not by itself make a route usable: the token registry must list
  the token with a deployment on both endpoints' CCTP domains.

- Reuse an `estimate` quote when bridging (CCTPx)

  Pass the `quote` returned by `estimate` into `bridge` so the fee you
  were quoted is the fee you pay. Treat the value as opaque and pass it
  back unmodified.

  Do not pass a quote into `estimate`. If the supplied quote is stale or
  does not match the requested fee token and speed, CCTPx fetches a fresh
  quote and adds `QUOTE_NOT_REUSED` to `result.warnings`, which means the
  fee paid may differ from the one quoted. A CCTPx quote passed to a
  plain USDC bridge is ignored. Re-estimate whenever the transfer
  changes.

## 1.14.1

### Patch Changes

- Fix `getSupportedChains({ sourceFeeSupported: true })` over-reporting source-fee
  bridging support. Previously, source-fee eligibility was inferred from a contract
  address shared with the fast-deposit forwarding path, causing fast-deposit-only chains
  to appear supported and fail at the Quote API instead of being rejected client-side.
  Source-fee support is now gated on an explicit allowlist of eligible source chains.

## 1.14.0

### Minor Changes

- Add Plasma (mainnet and testnet) support. Bridge USDC to and from Plasma via CCTP v2 in Bridge Kit and App Kit using `'Plasma'` or `'Plasma_Testnet'` as source or destination. No change required unless you want these routes.
- Bridge Kit and App Kit now support receive-exact forwarded USDC transfers with
  `config.feePayment: 'source'`. Estimates return the exact recipient amount,
  signed source-chain fee breakdown, total wallet debit, quote expiry, and an
  opaque signed quote. Caller-supplied quotes commit to the estimated price and
  are rejected when they are invalid, mismatched, expired, or too close to
  expiry; omitting the quote lets the kit fetch one automatically. Quote responses
  now support both timestamp and source-chain block expiries, and execution
  validates claimability against the current chain tip before burning.
  Source-fee bridges emit the same
  `approve`/`burn`/`mint` step events as the standard bridge path. The CCTP v2
  provider now also supports explicit mint recipient and destination-caller
  inputs for signed-fee burns and exposes `emitBridgeStep` for kit-level
  orchestration.

  Receive-exact source-paid fees are now available on every CCTP v2 EVM source
  chain the Fee Service supports (FAST where pre-finality is offered, otherwise
  STANDARD), rather than only the initial set of sources. Discover the
  source-fee-capable chains with
  `bridgeKit.getSupportedChains({ sourceFeeSupported: true })` or
  `appKit.getSupportedChains('bridge', { sourceFeeSupported: true })`.

### Patch Changes

- Forwarded EVM→Solana bridges now create the recipient's Associated Token
  Account (ATA). When a CCTP v2 burn is forwarded (`destination.useForwarder`) to
  a Solana destination, the provider emits `cctp-forward` hookData carrying
  `createAta` + the recipient's owner key, instructing Circle's relayer to create
  the recipient ATA (idempotently, at the relayer's expense) before minting. This
  prevents mints from targeting a non-existent ATA for fresh Solana wallets, which
  previously left forwarded transfers unclaimed. Bridges made through Bridge Kit
  and App Kit inherit this fix automatically.

  EVM destinations are unchanged — they continue to receive the empty forwarding
  frame. The CCTP v2 provider also exposes a new `getForwarderHookData` utility
  that builds the destination-appropriate forwarding frame.

## 1.13.0

### Minor Changes

- Add X Layer chain definitions (mainnet and testnet) with CCTP v2 support, USDC token addresses, Viem adapter mappings, Bridge Kit exports.

### Patch Changes

- Document custom fee policy methods in the README API reference, export the
  custom fee policy assertion for shared validation, and remove an unsupported
  method reference.

## 1.12.2

### Patch Changes

- Make the SDK safe to bundle and run in browsers/client-side apps.

  - Browser requests omit Node-only headers that would cause CORS failures, including EarnKit’s SDK-version header.
  - Solana operations in App Kit, Adapter Solana Kit, and Gateway work in a browser without requiring a consumer-provided `Buffer` polyfill.
  - Supplying a `kitKey` or Circle Wallets `apiKey` in a browser now fails early. Keep those secrets on the server and forward a prepared transaction or other safe result to the client.

## 1.12.1

### Patch Changes

- Internal dependency updates. No user-facing changes.

## 1.12.0

### Minor Changes

- Add support for bridging USDC to and from Cronos (mainnet and testnet) via CCTP v2.
- Add a `headers` config option to forward custom HTTP headers with CCTP
  attestation API requests.

  `CCTPV2Config`, `BridgeKitConfig`, and the AppKit context now accept an optional
  `headers` map. The headers are sent with every Circle attestation (Iris) API
  request the CCTP v2 provider makes — attestation fetch, re-attestation, and
  relayer mint status polling — and are merged on top of the SDK defaults (such
  as `Content-Type`) rather than replacing them.

## 1.11.1

### Patch Changes

- Internal dependency updates. No user-facing changes.

## 1.11.0

### Minor Changes

- The publicly re-exported `InputError` registry now includes three new
  chain pre-flight codes that the `/next` EVM adapters can throw:

  | Code   | Name                          |
  | ------ | ----------------------------- |
  | `1010` | `INPUT_CHAIN_MISMATCH`        |
  | `1011` | `INPUT_CHAIN_SWITCH_REJECTED` |
  | `1012` | `INPUT_UNRECOGNIZED_CHAIN`    |

  Consumers that branch on `InputError` (or on raw numeric codes) gain
  these values: `CHAIN_MISMATCH` when the connected wallet is on a
  different chain than the request targets, `CHAIN_SWITCH_REJECTED` when
  the user declines a programmatic switch, and `UNRECOGNIZED_CHAIN` when a
  chain definition cannot be resolved.

- **Behavioral change:** the re-exported `isRetryableError` no longer
  treats nonce errors (`4003` / `RPC_NONCE_ERROR`) as retryable.

  A nonce error is genuinely ambiguous — the transaction may already have
  been accepted (the nonce moved on), a concurrent transaction from the
  same key may have consumed the slot, or a local nonce tracker may have
  drifted. Generic automatic retry risks a double-spend or a
  nonce-conflict flip-flop, so `4003` was removed from
  `DEFAULT_RETRYABLE_ERROR_CODES` and callers must now decide explicitly
  whether to refresh the nonce and resubmit.

  For `@circle-fin/app-kit` specifically, the documented resume guard
  `if (isRetryableError(failedStep.error)) await kit.retryBridge(...)` now
  skips bridges that failed on a nonce error; handle code `4003` yourself
  if you want to refresh the nonce and retry.

### Patch Changes

- Error traces from BridgeKit, SwapKit, and UnifiedBalanceKit now carry the
  most recent on-chain transaction hash known to the failing operation,
  when one is available. BridgeKit walks the result steps (including
  pending broadcasts whose receipt has not yet landed). SwapKit and
  UnifiedBalanceKit capture the broadcast hash through a new internal
  `onBroadcast` callback threaded into the swap operation and into the
  gateway provider's `spend()` (as a new optional `options` argument with
  a `SpendOptions.onBroadcast` field).

- Fix forwarded-route support to depend only on the destination chain.

  `supportsRoute(source, destination, 'USDC', true)` previously also required the
  source chain's `cctp.forwarderSupported.source` to be `true`. Today's Forwarding
  Service operates on the destination chain, so any CCTP v2 chain can originate a
  forwarded transfer; the route check now gates only on the destination chain's
  `cctp.forwarderSupported.destination`, matching the bridge execution path.

  `cctp.forwarderSupported.source` is now `false` for every chain definition,
  reflecting that source-side forwarding is not yet available. This corrects
  metadata that previously implied source-side forwarding was supported.

  Also surfaced through `@circle-fin/bridge-kit` and `@circle-fin/app-kit`.

## 1.10.2

### Patch Changes

- `kit.bridge` no longer rejects Gas Station-enabled smart-contract accounts (SCAs) with zero native balance on the source or destination chain. EOA wallets without native funds will still fail at simulation with the underlying RPC error.

## 1.10.1

### Patch Changes

- Internal dependency updates. No user-facing changes.

## 1.10.0

### Minor Changes

- Add support for bridging USDC to and from Injective (mainnet and testnet) via CCTP v2. Both networks are now available as source and destination options in Bridge Kit.
- Add unhandled error telemetry reporting.
  - All kits now report unhandled errors to Circle's telemetry endpoint to aid reliability monitoring. Set `disableErrorReporting: true` in the kit config (or `AppKit` config) to opt out.
  - The following fields are included in each error report: error event type, SDK name and version, and where available: source chain name, destination chain name, and token symbol. Error messages, stack traces, wallet addresses, and transaction data are never sent.

## 1.9.0

### Minor Changes

- Add support for bridging USDC to and from Pharos (mainnet and testnet) via CCTP v2.

### Patch Changes

- Bridge errors now expose a machine-readable `errorCategory` so apps can distinguish user rejections, wallet capability errors, and offchain vs onchain failures without string-matching.
- The block explorer URLs returned in the Sei (mainnet and testnet) chain definitions now point to the current explorers. If you derive transaction or address links from `chain.blockExplorers`, your links will now resolve correctly.

## 1.8.3

### Patch Changes

- Chain definitions now include Gateway contract configuration for supported chains
- Fix burn step incorrectly reporting state "success" when on-chain transaction reverts

## 1.8.2

### Patch Changes

- Bridge operations that fail due to transient RPC errors during receipt polling now automatically retry with exponential backoff instead of failing permanently
- Update HyperEVM mainnet explorer URL to resolve location-restricted access issues
- Improved search discoverability

## 1.8.1

### Patch Changes

- Add support for Solana as a forwarder destination

## 1.8.0

### Minor Changes

- Enable forwarder destination support for Codex, Plume, and XDC chains on both mainnet and testnet

### Patch Changes

- Update HyperEVM explorer URLs to use the official Hyperliquid explorer

## 1.7.0

### Minor Changes

- Add support for bridging USDC to and from Edge and Morph networks. Both mainnet and testnet chains are now available as source and destination options in Bridge Kit.

## 1.6.1

### Patch Changes

- New error handling utilities for detecting rate-limit and service errors (`isRateLimitError`, `isServiceError`). Chain definitions now available via `@circle-fin/bridge-kit/chains` subpath import.

## 1.6.0

### Minor Changes

- Add Circle Forwarder support for CCTP v2 bridging.

  Forwarding is a relay-assisted mode where Circle observes the burn transaction,
  retrieves attestation data, and submits the destination mint on the user's
  behalf. This removes most destination-side orchestration from client code.

  What this enables:

  - Opt-in forwarding with `useForwarder: true` so Circle handles destination mint
    submission.
  - Forwarder-only destinations (no destination adapter required) using
    `{ recipientAddress, chain, useForwarder: true }`.
  - Forwarding-fee-aware estimation and max-fee calculation when `maxFee` is
    auto-derived.
  - New hook-based burn actions: `cctp.v2.depositForBurnWithHook` and
    `cctp.v2.customBurnWithHook`.
  - New forwarding helpers: `buildForwardingHookData` and
    `buildForwardingHookDataBuffer`.
  - Chain-level forwarding metadata via `cctp.forwarderSupported` for route
    capability checks.

  Compatibility:

  - Existing non-forwarded bridge flows remain unchanged.
  - If you set `config.maxFee` manually, include any expected forwarding fee.

## 1.5.0

### Minor Changes

- **Monad support**: Bridge Kit now supports Monad mainnet and testnet. You can include Monad in cross-chain USDC transfer flows without additional configuration or changes to existing integrations.

- **Automatic re-attestation for fast transfers**: When retrying a failed CCTP v2 fast transfer, the kit now automatically detects if the mint failed due to an expired attestation and triggers re-attestation. This eliminates manual intervention when attestations expire before the mint transaction completes.

## 1.4.0

### Minor Changes

- Add optional filtering to `getSupportedChains()` method to filter chains by type (EVM, Solana) and network (mainnet/testnet)

## 1.3.0

### Minor Changes

- **Enhanced bridge estimate response**: `EstimateResult` now includes `token`, `amount`, `source`, `destination` fields to provide complete transfer information alongside cost estimates.
- Export error handling utilities and constants.

New exports include:

- Error type guards: isKitError, isBalanceError, isOnchainError, isRpcError, isNetworkError, isRetryableError, isFatalError
- Error constants: BalanceError, OnchainError, RpcError, NetworkError, InputError
- Utility: getErrorCode, getErrorMessage

## 1.2.0

### Minor Changes

- Add computeFee function to CustomFeePolicy that receives human-readable amounts (e.g., '100' for 100 USDC), deprecate calculateFee which receives smallest-unit amounts
- Enhanced decimal format validation to standardize on strict dot (.) decimal separators. Amount, maxFee, and customFee fields now use a unified dot-decimal format. Supported examples include "1000.50" and "1.5"
- Introduce the `BridgeChain` enum and `BridgeChainIdentifier` type to restrict chain selection to only CCTPv2-supported chains. This provides IDE autocomplete limited to valid bridge chains and ensures that passing an unsupported chain triggers a compile-time error.

### Patch Changes

- Updated BridgeKit to return `BridgeResults` in human readable units for `bridge()` and `retry()`. For example, when printing out the results of a `kit.bridge()` call with 1 USDC, the result's `amount` attribute will now show `'1.0'` instead of `'1000000'`.
- Validation errors now use standardized error codes for consistent error handling. All validation failures return the same `KitError` structure as other SDK errors.

  **Migration:** If you're catching validation errors, update your error handling:

  - Check `error.code === 1098` instead of `instanceof ValidationError`
  - Access details via `error.cause?.trace?.validationErrors` instead of `error.errors`

  The legacy `ValidationError` class remains available for backward compatibility.

- Documented the exact custom-fee flow across Bridge Kit’s README and JSDoc.
  Clarified that kit-level and per-transfer custom fees are added to the transfer debit before CCTPv2 runs.

## 1.1.2

### Patch Changes

- Fixed bug where tokens could be burned when bridging to unsupported chains, and improved error messages to clearly show which chains are supported.

  **What's Fixed:**

  - **Prevents fund loss**: Bridge operations now fail immediately if your adapter doesn't support the source or destination chain, **before** any tokens are approved or burned. Previously, tokens could be burned on the source chain before discovering the destination chain was unsupported, requiring manual recovery.
  - **Better error messages**: When you attempt to use an unsupported chain, the error now clearly lists all chains your adapter supports, making it easy to pick an alternative:
    ```
    Invalid chain 'Linea Sepolia': Not supported by this adapter.
    It supports 17 chains: Arbitrum, Base, Ethereum, Polygon, Solana, ...
    ```
  - **Correct error codes**: Chain validation errors now use the correct `INVALID_CHAIN` error code instead of `UNSUPPORTED_ROUTE`, making it easier to handle errors programmatically.

## 1.1.1

### Patch Changes

- Fix CommonJS compatibility by correcting file extensions and package exports. This resolves a "ReferenceError: require is not defined" error that occurred when using packages in CommonJS projects with ts-node.

- Fixes a bug where the `recipientAddress` field in the `to` parameter was not being properly propagated to the underlying CCTP v2 provider. This caused custom recipient addresses to be ignored during cross-chain USDC transfers, resulting in funds being minted to the signer's address instead of the intended recipient.

  With this fix, when you specify a `recipientAddress` in the `to` parameter, the Bridge Kit now correctly passes it through to the provider, ensuring funds are minted to the correct address.

  **Example usage** (no changes needed if already using this pattern):

  ```typescript
  await kit.bridge({
    from: { adapter: sourceAdapter, chain: "Ethereum" },
    to: {
      adapter: destAdapter,
      chain: "Base",
      recipientAddress: "0x...", // Now properly respected
    },
    amount: "10",
    token: "USDC",
  });
  ```

  **No breaking changes** - existing code without `recipientAddress` continues to work unchanged. This fix only affects transfers where you explicitly provide a custom recipient address.

## 1.1.0

### Minor Changes

- Add automatic HTTP request tracking for analytics and debugging. The kit now automatically registers itself when the module loads, enabling Circle to track kit usage and identify issues. Applications can optionally set an external prefix using the new `setExternalPrefix` function to identify themselves in request analytics. All HTTP requests from the kit will include user agent information in the format: `[app/version] bridge-kit/version (runtime)`. This feature requires no code changes for existing users.

### Patch Changes

- Standardize `maxFee` parameter to accept human-readable values. The `maxFee` parameter in `BridgeConfig` now correctly accepts human-readable token amounts (e.g., `"1"` for 1 USDC, `"0.5"` for 0.5 USDC), matching the behavior of `customFee.value`. This resolves an undocumented inconsistency in the API. If you were previously passing values in smallest units, update to human-readable format: use `"1"` instead of `"1000000"` for 1 USDC.
- Complete CCTP v2 chain support exports

  Ensures all 35 chains with CCTP v2 support are properly exported from the `chains` entry point. This fix adds previously missing chain definitions including Codex, HyperEVM, Ink, Plume, Sei, Sonic, Unichain, WorldChain, and XDC networks (both mainnet and testnet variants where applicable).

- Add support for Arc Testnet chain definition. Arc is Circle's EVM-compatible Layer-1 blockchain designed for stablecoin finance and asset
  tokenization, featuring USDC as the native gas token and sub-second finality via the Malachite BFT consensus engine.
- Fix support for developer-controlled address context. Bridge operations now correctly accept an explicit `address` field in the context, allowing developer-controlled adapters to specify which address to use for operations. Previously, this field was incorrectly rejected at runtime.
- Update Sonic Testnet chain definition to canonical network. The `SonicTestnet` chain definition now points to the official Sonic Testnet (chainId: 14601) instead of the deprecated Sonic Blaze Testnet (chainId: 57054). The RPC endpoint has been updated to `https://rpc.testnet.soniclabs.com`, the display name simplified to "Sonic Testnet", and the USDC contract address updated to the new deployment.

  **Breaking Changes:**

  - **Chain ID:** 57054 → 14601
  - **RPC Endpoint:** `https://rpc.blaze.soniclabs.com` → `https://rpc.testnet.soniclabs.com`
  - **USDC Address:** `0xA4879Fed32Ecbef99399e5cbC247E533421C4eC6` → `0x0BA304580ee7c9a980CF72e55f5Ed2E9fd30Bc51`

  **Migration:** If you were using `SonicTestnet`, your application will automatically connect to the new network upon upgrading. Any accounts, contracts, or transactions on the old Blaze testnet (chainId: 57054) will need to be recreated on the new testnet.

## 1.0.0

### Major Changes

- # Bridge Kit 1.0.0 Release 🎉

  The core orchestration library for cross-chain USDC transfers - providing a unified, type-safe interface for bridging USDC between heterogeneous blockchain networks.

  ## 🚀 Core Features

  - **Complete Cross-chain Orchestration**: High-level API for USDC transfers between any supported chains
  - **Type-safe APIs**: Exhaustive runtime validation with strict TypeScript support
  - **Deterministic Operations**: Pre-flight simulations and predictable quote generation
  - **Comprehensive Finality Tracking**: Monitor transfer progress across all bridge steps

  ## 🔄 Intelligent Retry System

  Sophisticated retry mechanism that automatically handles failed or incomplete transfers:

  - **Automatic Recovery**: Resume transfers from the exact point of failure
  - **Step Analysis**: Intelligent detection of which operations completed successfully
  - **Network Resilience**: Handle temporary connectivity issues and gas estimation failures
  - **Multi-step Flow Support**: Retry complex bridge operations involving multiple blockchain transactions

  ```typescript
  // Retry a failed transfer with fresh adapter instances
  const retryResult = await kit.retry(failedResult, {
    from: sourceAdapter,
    to: destAdapter,
  });
  ```

  ## 💰 Flexible Fee Management

  Comprehensive fee system supporting both protocol fees and custom integrator fees:

  - **Transfer Speed Options**: Choose between FAST (with fees) and SLOW (fee-free) transfers
  - **Dynamic Fee Calculation**: Automatic fee estimation based on transfer amount and network conditions
  - **Custom Fee Policies**: Implement your own fee structures with absolute amounts
  - **Multi-chain Fee Support**: Different fee configurations per source chain
  - **Fee Recipient Control**: Specify where fees are sent on the source chain

  ```typescript
  // Set custom fee policy
  kit.setCustomFeePolicy({
    calculateFee: (params) =>
      params.from.chain.type === "solana" ? "0.1" : "0.2",
    resolveFeeRecipientAddress: (chain) => getFeeRecipientForChain(chain),
  });
  ```

  ## 🎯 Use Cases

  - **Multi-chain dApp Integration**: Single SDK for all cross-chain USDC needs
  - **Wallet Integration**: Seamless cross-chain transfers for end users
  - **Exchange Integration**: Institutional-grade cross-chain USDC movement
  - **DeFi Protocol Integration**: Bridge USDC liquidity across ecosystems

  This release provides the foundational orchestration layer for cross-chain USDC applications with production-ready reliability and comprehensive developer tooling.
