@circle-fin/bridge-kit 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -400,10 +400,16 @@ type KitContractType = 'bridge';
400
400
  */
401
401
  type KitContracts = Partial<Record<KitContractType, string>>;
402
402
  /**
403
- * Enumeration of all blockchains supported by this library.
403
+ * Enumeration of all blockchains known to this library.
404
+ *
405
+ * This enum contains every blockchain that has a chain definition, regardless
406
+ * of whether bridging is currently supported. For chains that support bridging
407
+ * via CCTPv2, see {@link BridgeChain}.
408
+ *
404
409
  * @enum
405
410
  * @category Enums
406
- * @description Provides string identifiers for each supported blockchain.
411
+ * @description Provides string identifiers for each blockchain with a definition.
412
+ * @see {@link BridgeChain} for the subset of chains that support CCTPv2 bridging.
407
413
  */
408
414
  declare enum Blockchain {
409
415
  Algorand = "Algorand",
@@ -462,6 +468,143 @@ declare enum Blockchain {
462
468
  ZKSync_Era = "ZKSync_Era",
463
469
  ZKSync_Sepolia = "ZKSync_Sepolia"
464
470
  }
471
+ /**
472
+ * Enumeration of blockchains that support cross-chain bridging via CCTPv2.
473
+ *
474
+ * The enum is derived from the full {@link Blockchain} enum but filtered to only
475
+ * include chains with active CCTPv2 support. When new chains gain CCTPv2 support,
476
+ * they are added to this enum.
477
+ *
478
+ * @enum
479
+ * @category Enums
480
+ *
481
+ * @remarks
482
+ * - This enum is the **canonical source** of bridging-supported chains.
483
+ * - Use this enum (or its string literals) in `kit.bridge()` calls for type safety.
484
+ * - Attempting to use a chain not in this enum will produce a TypeScript compile error.
485
+ *
486
+ * @example
487
+ * ```typescript
488
+ * import { BridgeKit, BridgeChain } from '@circle-fin/bridge-kit'
489
+ *
490
+ * const kit = new BridgeKit()
491
+ *
492
+ * // ✅ Valid - autocomplete suggests only supported chains
493
+ * await kit.bridge({
494
+ * from: { adapter, chain: BridgeChain.Ethereum },
495
+ * to: { adapter, chain: BridgeChain.Base },
496
+ * amount: '100'
497
+ * })
498
+ *
499
+ * // ✅ Also valid - string literals work with autocomplete
500
+ * await kit.bridge({
501
+ * from: { adapter, chain: 'Ethereum_Sepolia' },
502
+ * to: { adapter, chain: 'Base_Sepolia' },
503
+ * amount: '100'
504
+ * })
505
+ *
506
+ * // ❌ Compile error - Algorand is not in BridgeChain
507
+ * await kit.bridge({
508
+ * from: { adapter, chain: 'Algorand' }, // TypeScript error!
509
+ * to: { adapter, chain: 'Base' },
510
+ * amount: '100'
511
+ * })
512
+ * ```
513
+ *
514
+ * @see {@link Blockchain} for the complete list of all known blockchains.
515
+ * @see {@link BridgeChainIdentifier} for the type that accepts these values.
516
+ */
517
+ declare enum BridgeChain {
518
+ Arbitrum = "Arbitrum",
519
+ Avalanche = "Avalanche",
520
+ Base = "Base",
521
+ Codex = "Codex",
522
+ Ethereum = "Ethereum",
523
+ HyperEVM = "HyperEVM",
524
+ Ink = "Ink",
525
+ Linea = "Linea",
526
+ Optimism = "Optimism",
527
+ Plume = "Plume",
528
+ Polygon = "Polygon",
529
+ Sei = "Sei",
530
+ Solana = "Solana",
531
+ Sonic = "Sonic",
532
+ Unichain = "Unichain",
533
+ World_Chain = "World_Chain",
534
+ XDC = "XDC",
535
+ Arc_Testnet = "Arc_Testnet",
536
+ Arbitrum_Sepolia = "Arbitrum_Sepolia",
537
+ Avalanche_Fuji = "Avalanche_Fuji",
538
+ Base_Sepolia = "Base_Sepolia",
539
+ Codex_Testnet = "Codex_Testnet",
540
+ Ethereum_Sepolia = "Ethereum_Sepolia",
541
+ HyperEVM_Testnet = "HyperEVM_Testnet",
542
+ Ink_Testnet = "Ink_Testnet",
543
+ Linea_Sepolia = "Linea_Sepolia",
544
+ Optimism_Sepolia = "Optimism_Sepolia",
545
+ Plume_Testnet = "Plume_Testnet",
546
+ Polygon_Amoy_Testnet = "Polygon_Amoy_Testnet",
547
+ Sei_Testnet = "Sei_Testnet",
548
+ Solana_Devnet = "Solana_Devnet",
549
+ Sonic_Testnet = "Sonic_Testnet",
550
+ Unichain_Sepolia = "Unichain_Sepolia",
551
+ World_Chain_Sepolia = "World_Chain_Sepolia",
552
+ XDC_Apothem = "XDC_Apothem"
553
+ }
554
+ /**
555
+ * Type representing valid bridge chain identifiers.
556
+ *
557
+ * This type constrains chain parameters to only accept chains that support CCTPv2 bridging
558
+ *
559
+ * Accepts:
560
+ * - A {@link BridgeChain} enum value (e.g., `BridgeChain.Ethereum`)
561
+ * - A string literal matching a BridgeChain value (e.g., `'Ethereum'`)
562
+ * - A {@link ChainDefinition} object for a supported chain
563
+ *
564
+ * @example
565
+ * ```typescript
566
+ * import type { BridgeChainIdentifier } from '@circle-fin/bridge-kit'
567
+ * import { BridgeChain } from '@circle-fin/bridge-kit'
568
+ * import { Solana } from '@circle-fin/bridge-kit/chains'
569
+ *
570
+ * // All of these are valid BridgeChainIdentifier values:
571
+ * const chain1: BridgeChainIdentifier = BridgeChain.Ethereum
572
+ * const chain2: BridgeChainIdentifier = 'Base_Sepolia'
573
+ * const chain3: BridgeChainIdentifier = Solana // ChainDefinition
574
+ *
575
+ * // This will cause a TypeScript error:
576
+ * const chain4: BridgeChainIdentifier = 'Algorand' // Error!
577
+ * ```
578
+ *
579
+ * @see {@link BridgeChain} for the enum of supported chains.
580
+ * @see {@link ChainIdentifier} for the less restrictive type accepting all chains.
581
+ */
582
+ type BridgeChainIdentifier = ChainDefinition | BridgeChain | `${BridgeChain}`;
583
+
584
+ /**
585
+ * Resolves a flexible chain identifier to a ChainDefinition.
586
+ *
587
+ * This function handles all three supported formats:
588
+ * - ChainDefinition objects (passed through unchanged)
589
+ * - Blockchain enum values (resolved via getChainByEnum)
590
+ * - String literals of blockchain values (resolved via getChainByEnum)
591
+ *
592
+ * @param chainIdentifier - The chain identifier to resolve
593
+ * @returns The resolved ChainDefinition object
594
+ * @throws Error if the chain identifier cannot be resolved
595
+ *
596
+ * @example
597
+ * ```typescript
598
+ * import { resolveChainIdentifier } from '@core/chains'
599
+ * import { Blockchain, Ethereum } from '@core/chains'
600
+ *
601
+ * // All of these resolve to the same ChainDefinition:
602
+ * const chain1 = resolveChainIdentifier(Ethereum)
603
+ * const chain2 = resolveChainIdentifier(Blockchain.Ethereum)
604
+ * const chain3 = resolveChainIdentifier('Ethereum')
605
+ * ```
606
+ */
607
+ declare function resolveChainIdentifier(chainIdentifier: ChainIdentifier): ChainDefinition;
465
608
 
466
609
  /**
467
610
  * Core type definitions for blockchain transaction execution and gas estimation.
@@ -1179,6 +1322,14 @@ interface CCTPv2ActionMap {
1179
1322
  * the adapter's default address.
1180
1323
  */
1181
1324
  readonly destinationAddress?: string;
1325
+ /**
1326
+ * The mint recipient address from the decoded CCTP message.
1327
+ *
1328
+ * This is the actual address encoded in the burn message where tokens will be minted.
1329
+ * For Solana, this is already the Associated Token Account (ATA) address, not the owner.
1330
+ * For EVM chains, this is the recipient's wallet address.
1331
+ */
1332
+ readonly mintRecipient?: string;
1182
1333
  };
1183
1334
  /**
1184
1335
  * Initiate a cross-chain USDC transfer using a custom bridge contract with preapproval funnel.
@@ -1870,10 +2021,9 @@ declare class ActionRegistry {
1870
2021
  * @param params - The parameters to pass to the action handler.
1871
2022
  * @param context - The resolved operation context with concrete chain and address values.
1872
2023
  * @returns A promise resolving to the prepared chain request.
1873
- *
1874
- * @throws {Error} When action parameter is not a valid string.
2024
+ * @throws {KitError} When the handler execution fails with a structured error.
1875
2025
  * @throws {Error} When no handler is registered for the specified action.
1876
- * @throws {Error} When the handler execution fails.
2026
+ * @throws {Error} When the handler execution fails with an unstructured error.
1877
2027
  *
1878
2028
  * @example
1879
2029
  * ```typescript
@@ -2120,10 +2270,10 @@ declare abstract class Adapter<TAdapterCapabilities extends AdapterCapabilities
2120
2270
  * This address is used as the default sender for transactions
2121
2271
  * and interactions initiated by this adapter.
2122
2272
  *
2123
- * @param chain - Optional chain definition for chain-specific address resolution (used by EVM adapters)
2273
+ * @param chain - The chain to use for address resolution.
2124
2274
  * @returns A promise that resolves to the blockchain address as a string.
2125
2275
  */
2126
- abstract getAddress(chain?: ChainDefinition): Promise<string>;
2276
+ abstract getAddress(chain: ChainDefinition): Promise<string>;
2127
2277
  /**
2128
2278
  * Switches the adapter to operate on the specified chain.
2129
2279
  *
@@ -2194,7 +2344,7 @@ declare abstract class Adapter<TAdapterCapabilities extends AdapterCapabilities
2194
2344
  * Validate that the target chain is supported by this adapter.
2195
2345
  *
2196
2346
  * @param targetChain - The chain to validate.
2197
- * @throws Error if the chain is not supported.
2347
+ * @throws KitError with INVALID_CHAIN code if the chain is not supported by this adapter.
2198
2348
  */
2199
2349
  validateChainSupport(targetChain: ChainDefinition): void;
2200
2350
  /**
@@ -2583,6 +2733,14 @@ interface BridgeResult {
2583
2733
  address: string;
2584
2734
  /** The destination blockchain network */
2585
2735
  chain: ChainDefinition;
2736
+ /**
2737
+ * Optional custom recipient address for minted funds.
2738
+ *
2739
+ * When provided during the bridge operation, minted tokens are sent to this
2740
+ * address instead of the destination address. This field is preserved in the
2741
+ * result for retry operations to maintain consistency with the original burn.
2742
+ */
2743
+ recipientAddress?: string;
2586
2744
  };
2587
2745
  /** Array of steps that were executed during the bridge process */
2588
2746
  steps: BridgeStep[];
@@ -2672,6 +2830,40 @@ interface BridgeConfig {
2672
2830
  maxFee?: string;
2673
2831
  /**
2674
2832
  * The custom fee to charge for the transfer.
2833
+ *
2834
+ * Whatever value you provide here is **added on top of the transfer amount**. The user must have
2835
+ * enough balance for `amount + customFee`, and the wallet signs for that total on the source
2836
+ * chain. The custom fee is split automatically:
2837
+ *
2838
+ * - 10% routes to Circle.
2839
+ * - 90% routes to your `recipientAddress`.
2840
+ *
2841
+ * The original transfer amount proceeds through CCTPv2 unchanged, and the protocol fee (1–14 bps
2842
+ * in FAST mode, 0% in STANDARD) is taken from that transfer amount.
2843
+ *
2844
+ * @example
2845
+ * ```typescript
2846
+ * import type { BridgeConfig } from '@core/provider'
2847
+ *
2848
+ * const config: BridgeConfig = {
2849
+ * customFee: {
2850
+ * value: '5', // 5 USDC developer fee
2851
+ * recipientAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0',
2852
+ * },
2853
+ * }
2854
+ *
2855
+ * // Fee flow for a 100 USDC transfer with 5 USDC custom fee:
2856
+ * // Source chain (Ethereum):
2857
+ * // - Wallet debits: 105 USDC total (100 transfer + 5 custom fee)
2858
+ * // - Custom fee split: 0.5 USDC (10%) → Circle, 4.5 USDC (90%) → your recipientAddress
2859
+ * // - Amount sent to CCTPv2: 100 USDC (unchanged)
2860
+ * //
2861
+ * // Destination chain (Base):
2862
+ * // - CCTPv2 FAST fee (example: 1 bps): ~0.01 USDC deducted
2863
+ * // - User receives: ~99.99 USDC
2864
+ * //
2865
+ * // Note: Actual CCTP fees vary by route (1-14 bps for FAST, 0 bps for STANDARD)
2866
+ * ```
2675
2867
  */
2676
2868
  customFee?: CustomFee | undefined;
2677
2869
  }
@@ -2714,6 +2906,10 @@ interface CustomFee {
2714
2906
  * bridge transfer. The fee recipient address **must be a valid address for
2715
2907
  * the source chain** of the bridge transfer.
2716
2908
  *
2909
+ * @remarks
2910
+ * Circle automatically receives 10% of every custom fee; the remaining 90% is
2911
+ * sent to this `recipientAddress`.
2912
+ *
2717
2913
  * For example: if bridging from Ethereum to Solana, pass an EVM address like
2718
2914
  * `"0x1234567890123456789012345678901234567890"` because the source chain
2719
2915
  * is Ethereum.
@@ -2736,6 +2932,7 @@ interface CustomFee {
2736
2932
  * and address requirements are enforced at compile time based on adapter capabilities.
2737
2933
  *
2738
2934
  * @typeParam TAdapterCapabilities - The adapter capabilities type to derive address requirements from
2935
+ * @typeParam TChainIdentifier - The chain identifier type constraint (defaults to ChainIdentifier)
2739
2936
  *
2740
2937
  * @example
2741
2938
  * ```typescript
@@ -2754,11 +2951,11 @@ interface CustomFee {
2754
2951
  * }
2755
2952
  * ```
2756
2953
  */
2757
- type AdapterContext<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> = {
2954
+ type AdapterContext<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends ChainIdentifier = ChainIdentifier> = {
2758
2955
  /** The adapter instance for blockchain operations */
2759
2956
  adapter: Adapter<TAdapterCapabilities>;
2760
2957
  /** The chain reference, which can be a ChainDefinition, Blockchain enum, or string literal */
2761
- chain: ChainIdentifier;
2958
+ chain: TChainIdentifier;
2762
2959
  } & AddressField<ExtractAddressContext<TAdapterCapabilities>>;
2763
2960
  /**
2764
2961
  * Represents a bridge destination with an explicit custom recipient address.
@@ -2769,6 +2966,7 @@ type AdapterContext<TAdapterCapabilities extends AdapterCapabilities = AdapterCa
2769
2966
  * the destination adapter.
2770
2967
  *
2771
2968
  * @typeParam TCapabilities - The adapter capabilities type for the destination adapter
2969
+ * @typeParam TChainIdentifier - The chain identifier type constraint (defaults to ChainIdentifier)
2772
2970
  *
2773
2971
  * @remarks
2774
2972
  * The `recipientAddress` must be a valid address format for the destination chain
@@ -2789,7 +2987,7 @@ type AdapterContext<TAdapterCapabilities extends AdapterCapabilities = AdapterCa
2789
2987
  * }
2790
2988
  * ```
2791
2989
  */
2792
- type BridgeDestinationWithAddress<TCapabilities extends AdapterCapabilities = AdapterCapabilities> = AdapterContext<TCapabilities> & {
2990
+ type BridgeDestinationWithAddress<TCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends ChainIdentifier = ChainIdentifier> = AdapterContext<TCapabilities, TChainIdentifier> & {
2793
2991
  /**
2794
2992
  * The custom recipient address on the destination chain.
2795
2993
  *
@@ -2801,8 +2999,11 @@ type BridgeDestinationWithAddress<TCapabilities extends AdapterCapabilities = Ad
2801
2999
  /**
2802
3000
  * Union type representing a bridge destination.
2803
3001
  * Can be either an AdapterContext (for default recipient) or BridgeDestinationWithAddress (for explicit recipient).
3002
+ *
3003
+ * @typeParam TAdapterCapabilities - The adapter capabilities type for the destination adapter
3004
+ * @typeParam TChainIdentifier - The chain identifier type constraint (defaults to ChainIdentifier)
2804
3005
  */
2805
- type BridgeDestination<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> = AdapterContext<TAdapterCapabilities> | BridgeDestinationWithAddress<TAdapterCapabilities>;
3006
+ type BridgeDestination<TAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TChainIdentifier extends ChainIdentifier = ChainIdentifier> = AdapterContext<TAdapterCapabilities, TChainIdentifier> | BridgeDestinationWithAddress<TAdapterCapabilities, TChainIdentifier>;
2806
3007
  /**
2807
3008
  * Context for retry operations containing source and destination adapter contexts.
2808
3009
  *
@@ -2945,7 +3146,7 @@ declare abstract class BridgingProvider<TProviderActions = Record<string, unknow
2945
3146
  * @param token - The token to bridge (currently only USDC is supported)
2946
3147
  * @param config - Optional bridge configuration including speed and fee settings
2947
3148
  * @returns Promise resolving to the bridge result with transaction details and steps
2948
- * @throws {ValidationError} If the parameters are invalid
3149
+ * @throws {KitError} If the parameters are invalid
2949
3150
  * @throws {UnsupportedRouteError} If the route is not supported
2950
3151
  * @throws {BridgeError} If the bridge operation fails
2951
3152
  *
@@ -2970,7 +3171,7 @@ declare abstract class BridgingProvider<TProviderActions = Record<string, unknow
2970
3171
  *
2971
3172
  * @param params - The bridge parameters for cost estimation
2972
3173
  * @returns Promise resolving to the cost estimate including gas and protocol fees
2973
- * @throws {ValidationError} If the parameters are invalid
3174
+ * @throws {KitError} If the parameters are invalid
2974
3175
  * @throws {UnsupportedRouteError} If the route is not supported
2975
3176
  *
2976
3177
  * @example
@@ -3096,44 +3297,62 @@ declare abstract class BridgingProvider<TProviderActions = Record<string, unknow
3096
3297
  analyzeStepsForRetry(steps: BridgeStep[]): StepAnalysisResult;
3097
3298
  }
3098
3299
 
3300
+ type FeeFunction<TFromAdapterCapabilities extends AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities> = (params: BridgeParams$1<TFromAdapterCapabilities, TToAdapterCapabilities>) => Promise<string> | string;
3301
+ type FeeRecipientFunction<TFromAdapterCapabilities extends AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities> = (feePayoutChain: ChainDefinition, params: BridgeParams$1<TFromAdapterCapabilities, TToAdapterCapabilities>) => Promise<string> | string;
3099
3302
  /**
3100
3303
  * Custom fee policy for BridgeKit.
3101
3304
  *
3102
- * Provides hooks to calculate an absolute fee (in smallest unit string)
3103
- * and to resolve the fee recipient address on the source chain.
3305
+ * Provides hooks to calculate an absolute custom fee and resolve the fee recipient address
3306
+ * on the source chain. The returned fee is **added on top of the transfer amount** (the wallet signs for
3307
+ * `amount + customFee`). Once collected, the custom fee is split:
3308
+ *
3309
+ * - **10%** automatically routes to Circle.
3310
+ * - **90%** routes to your supplied `recipientAddress`.
3311
+ *
3312
+ * The entire transfer amount still flows through CCTPv2, which then charges its own protocol fee.
3313
+ *
3314
+ * Use `computeFee` (recommended) for human-readable amounts, or `calculateFee` (deprecated)
3315
+ * for smallest-unit amounts. Only one should be provided.
3104
3316
  *
3105
3317
  * @example
3106
3318
  * ```typescript
3107
3319
  * import type { CustomFeePolicy, BridgeParams } from '@circle-fin/bridge-kit'
3108
3320
  *
3109
3321
  * const policy: CustomFeePolicy = {
3110
- * // Charge 1 USDC on Solana, 0 on Ethereum, else 2 USDC
3111
- * calculateFee: (params: BridgeParams): string => {
3112
- * if (params.from.chain.type === 'solana') return '1000000'
3113
- * if (params.from.chain.name === 'Ethereum') return '0'
3114
- * return '2000000'
3115
- * },
3116
- * // Return a valid fee recipient for the source chain
3117
- * resolveFeeRecipientAddress: (feePayoutChain): string => {
3118
- * if (feePayoutChain.type === 'solana') {
3119
- * return 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
3120
- * }
3121
- * return '0x1234567890123456789012345678901234567890'
3322
+ * // computeFee receives human-readable amounts (e.g., '100' for 100 USDC)
3323
+ * computeFee: (params: BridgeParams) => {
3324
+ * const amount = parseFloat(params.amount)
3325
+ *
3326
+ * // 1% fee, capped between 5-50 USDC
3327
+ * const fee = Math.min(Math.max(amount * 0.01, 5), 50)
3328
+ * return fee.toFixed(6)
3122
3329
  * },
3330
+ * resolveFeeRecipientAddress: (feePayoutChain) =>
3331
+ * feePayoutChain.type === 'solana'
3332
+ * ? 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
3333
+ * : '0x1234567890123456789012345678901234567890',
3123
3334
  * }
3124
3335
  * ```
3125
3336
  */
3126
- interface CustomFeePolicy {
3337
+ type CustomFeePolicy = {
3127
3338
  /**
3128
3339
  * A function that returns the fee to charge for the bridge transfer.
3129
- * The value returned from the function represents an absolute fee in the smallest unit of the token.
3130
- * It **does not** represent a percentage fee, only an absolute value.
3131
- *
3132
- * For example: if you want to charge 1 USDC, you would return `'1000000'`.
3340
+ * The value returned from the function represents an absolute fee.
3341
+ * The returned fee is **added on top of the transfer amount**. For example, returning
3342
+ * `'5'` (5 USDC) for a 100 USDC transfer causes the wallet to debit 105 USDC total.
3343
+ * CCTPv2 still processes the full 100 USDC transfer amount, while the custom fee is split
3344
+ * 10%/90% between Circle and your fee recipient.
3133
3345
  *
3134
- * Note: returning `'0'` will result in no fee being charged.
3346
+ * @example
3347
+ * ```typescript
3348
+ * computeFee: (params) => {
3349
+ * const amount = parseFloat(params.amount)
3350
+ * return (amount * 0.01).toString() // 1% fee
3351
+ * }
3352
+ * ```
3135
3353
  */
3136
- calculateFee: <TFromAdapterCapabilities extends AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities>(params: BridgeParams$1<TFromAdapterCapabilities, TToAdapterCapabilities>) => Promise<string> | string;
3354
+ computeFee: FeeFunction<AdapterCapabilities, AdapterCapabilities>;
3355
+ calculateFee?: never;
3137
3356
  /**
3138
3357
  * A function that returns the fee recipient for a bridge transfer.
3139
3358
  * The value returned from the function represents the address that will receive the fee on the source chain of the bridge transfer.
@@ -3142,18 +3361,27 @@ interface CustomFeePolicy {
3142
3361
  * For example: if you are bridging from Ethereum to Solana you would return `'0x1234567890123456789012345678901234567890'`,
3143
3362
  * because the source chain of the bridge transfer is Ethereum.
3144
3363
  */
3145
- resolveFeeRecipientAddress: <TFromAdapterCapabilities extends AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities>(
3364
+ resolveFeeRecipientAddress: FeeRecipientFunction<AdapterCapabilities, AdapterCapabilities>;
3365
+ } | {
3366
+ computeFee?: never;
3146
3367
  /**
3147
- * The chain definition for the chain on which the fee is paid (the source chain).
3148
- * For example, when bridging from Ethereum to Base, the fee payout chain is Ethereum,
3149
- * since the bridging originates on Ethereum and the fee is taken on the source chain.
3368
+ * Calculate the fee to charge for the bridge transfer using smallest-unit amounts.
3369
+ *
3370
+ * @deprecated Use `computeFee` instead, which receives human-readable amounts.
3371
+ *
3372
+ * The `params.amount` is in smallest units (e.g., `'100000000'` for 100 USDC).
3150
3373
  */
3151
- feePayoutChain: ChainDefinition,
3374
+ calculateFee: FeeFunction<AdapterCapabilities, AdapterCapabilities>;
3152
3375
  /**
3153
- * The bridge parameters.
3376
+ * A function that returns the fee recipient for a bridge transfer.
3377
+ * The value returned from the function represents the address that will receive the fee on the source chain of the bridge transfer.
3378
+ * The fee recipient address **must be a valid address for the source chain** of the bridge transfer.
3379
+ *
3380
+ * For example: if you are bridging from Ethereum to Solana you would return `'0x1234567890123456789012345678901234567890'`,
3381
+ * because the source chain of the bridge transfer is Ethereum.
3154
3382
  */
3155
- params: BridgeParams$1<TFromAdapterCapabilities, TToAdapterCapabilities>) => Promise<string> | string;
3156
- }
3383
+ resolveFeeRecipientAddress: FeeRecipientFunction<AdapterCapabilities, AdapterCapabilities>;
3384
+ };
3157
3385
  /**
3158
3386
  * Parameters for initiating a cross-chain USDC bridge transfer.
3159
3387
  *
@@ -3165,46 +3393,69 @@ interface CustomFeePolicy {
3165
3393
  * - The `config` field allows customization of bridge behavior (e.g., transfer speed).
3166
3394
  * - The `token` field is optional and defaults to 'USDC'; other tokens are not currently supported.
3167
3395
  *
3168
- * @typeParam TChainDefinition - The chain definition type for advanced usage (defaults to {@link ChainDefinition}).
3396
+ * @typeParam TFromAdapterCapabilities - The source adapter capabilities type.
3397
+ * @typeParam TToAdapterCapabilities - The destination adapter capabilities type.
3169
3398
  *
3170
3399
  * @example
3171
3400
  * ```typescript
3401
+ * import { BridgeKit, BridgeChain } from '@circle-fin/bridge-kit'
3402
+ *
3403
+ * const kit = new BridgeKit()
3404
+ *
3405
+ * // Using BridgeChain enum values (full autocomplete support)
3172
3406
  * const params: BridgeParams = {
3173
- * from: { adapter: sourceAdapter, chain: 'Ethereum' },
3174
- * to: { adapter: destAdapter, chain: 'Base' },
3407
+ * from: { adapter: sourceAdapter, chain: BridgeChain.Ethereum },
3408
+ * to: { adapter: destAdapter, chain: BridgeChain.Base },
3175
3409
  * amount: '10.5',
3176
- * // Optional:
3177
3410
  * config: { transferSpeed: 'FAST' },
3178
3411
  * token: 'USDC'
3179
3412
  * }
3180
3413
  *
3181
- * // Or with explicit recipient address:
3414
+ * // Using string literals (also works with autocomplete)
3415
+ * const params2: BridgeParams = {
3416
+ * from: { adapter: sourceAdapter, chain: 'Ethereum_Sepolia' },
3417
+ * to: { adapter: destAdapter, chain: 'Base_Sepolia' },
3418
+ * amount: '10.5'
3419
+ * }
3420
+ *
3421
+ * // With explicit recipient address:
3182
3422
  * const paramsWithAddress: BridgeParams = {
3183
- * from: { adapter: sourceAdapter, chain: 'Ethereum' },
3423
+ * from: { adapter: sourceAdapter, chain: BridgeChain.Ethereum },
3184
3424
  * to: {
3185
3425
  * recipientAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
3186
- * adapter: destAdapter, chain: 'Base'
3426
+ * adapter: destAdapter,
3427
+ * chain: BridgeChain.Base
3187
3428
  * },
3188
3429
  * amount: '10.5'
3189
3430
  * }
3431
+ *
3432
+ * // ❌ Compile error - Algorand is not a supported bridge chain
3433
+ * const invalidParams: BridgeParams = {
3434
+ * from: { adapter: sourceAdapter, chain: 'Algorand' }, // TypeScript error!
3435
+ * to: { adapter: destAdapter, chain: 'Base' },
3436
+ * amount: '10.5'
3437
+ * }
3190
3438
  * ```
3439
+ *
3440
+ * @see {@link BridgeChain} for the enum of supported chains.
3441
+ * @see {@link BridgeChainIdentifier} for the type of valid chain values.
3191
3442
  */
3192
3443
  interface BridgeParams<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> {
3193
3444
  /**
3194
3445
  * The source adapter context (wallet and chain) for the transfer.
3195
3446
  */
3196
- from: AdapterContext<TFromAdapterCapabilities>;
3447
+ from: AdapterContext<TFromAdapterCapabilities, BridgeChainIdentifier>;
3197
3448
  /**
3198
- * The destination for the transfer, supporting explicit or derived recipient addresses.
3449
+ * The destination for the transfer, supporting explicit or derived recipient addresses
3199
3450
  */
3200
- to: BridgeDestination<TToAdapterCapabilities>;
3451
+ to: BridgeDestination<TToAdapterCapabilities, BridgeChainIdentifier>;
3201
3452
  /**
3202
- * The amount to transfer.
3453
+ * The amount to transfer
3203
3454
  */
3204
3455
  amount: string;
3205
3456
  /**
3206
3457
  * Optional bridge configuration (e.g., transfer speed).
3207
- * If omitted, defaults will be used.
3458
+ * If omitted, defaults will be used
3208
3459
  */
3209
3460
  config?: BridgeConfig;
3210
3461
  /**
@@ -3242,8 +3493,9 @@ declare const getDefaultProviders: () => readonly [CCTPV2BridgingProvider];
3242
3493
  *
3243
3494
  * // Set custom fee policy using the setter method
3244
3495
  * kit.setCustomFeePolicy({
3245
- * calculateFee: (params: BridgeParams): string => {
3246
- * return '1000000' // 1 USDC
3496
+ * computeFee: (params: BridgeParams): string => {
3497
+ * const amount = parseFloat(params.amount)
3498
+ * return (amount * 0.01).toFixed(6) // 1% fee
3247
3499
  * },
3248
3500
  * resolveFeeRecipientAddress: (chain: ChainDefinition): string => {
3249
3501
  * return '0x1234567890123456789012345678901234567890'
@@ -3402,18 +3654,18 @@ type FlexibleBridgingProvider = BridgingProvider<any>;
3402
3654
  *
3403
3655
  * @param params - The bridge parameters containing source, destination, amount, and token
3404
3656
  * @returns Promise resolving to the bridge result with transaction details and steps
3405
- * @throws {ValidationError} If the parameters are invalid
3657
+ * @throws {KitError} If the parameters are invalid
3406
3658
  * @throws {BridgeError} If the bridging process fails
3407
3659
  * @throws {UnsupportedRouteError} If the route is not supported
3408
3660
  *
3409
3661
  * @example
3410
3662
  * ```typescript
3411
3663
  * import { BridgeKit } from '@circle-fin/bridge-kit'
3412
- * import { createAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
3664
+ * import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
3413
3665
  *
3414
3666
  * // Create kit with default CCTPv2 provider
3415
3667
  * const kit = new BridgeKit()
3416
- * const adapter = createAdapterFromPrivateKey({ privateKey: '0x...' })
3668
+ * const adapter = createViemAdapterFromPrivateKey({ privateKey: '0x...' })
3417
3669
  *
3418
3670
  * // Execute cross-chain transfer
3419
3671
  * const result = await kit.bridge({
@@ -3534,18 +3786,18 @@ declare class BridgeKit<TExtraProviders extends FlexibleBridgingProvider[] = []>
3534
3786
  *
3535
3787
  * @param params - The transfer parameters containing source, destination, amount, and token
3536
3788
  * @returns Promise resolving to the transfer result with transaction details and steps
3537
- * @throws {ValidationError} When any parameter validation fails.
3789
+ * @throws {KitError} When any parameter validation fails.
3538
3790
  * @throws {Error} When CCTPv2 does not support the specified route.
3539
3791
  *
3540
3792
  * @example
3541
3793
  * ```typescript
3542
3794
  * import { BridgeKit } from '@circle-fin/bridge-kit'
3543
- * import { createAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
3795
+ * import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
3544
3796
  *
3545
3797
  * const kit = new BridgeKit()
3546
3798
  *
3547
3799
  * // Create a single adapter that can work across chains
3548
- * const adapter = createAdapterFromPrivateKey({
3800
+ * const adapter = createViemAdapterFromPrivateKey({
3549
3801
  * privateKey: process.env.PRIVATE_KEY,
3550
3802
  * })
3551
3803
  *
@@ -3604,10 +3856,14 @@ declare class BridgeKit<TExtraProviders extends FlexibleBridgingProvider[] = []>
3604
3856
  * @example
3605
3857
  * ```typescript
3606
3858
  * import { BridgeKit } from '@circle-fin/bridge-kit'
3607
- * import { createAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
3859
+ * import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
3608
3860
  *
3609
3861
  * const kit = new BridgeKit()
3610
3862
  *
3863
+ * // Create adapters for source and destination chains
3864
+ * const sourceAdapter = createViemAdapterFromPrivateKey({ privateKey: '...' })
3865
+ * const destAdapter = createViemAdapterFromPrivateKey({ privateKey: '...' })
3866
+ *
3611
3867
  * // Assume we have a failed bridge result from a previous operation
3612
3868
  * const failedResult: BridgeResult = {
3613
3869
  * state: 'error',
@@ -3643,7 +3899,7 @@ declare class BridgeKit<TExtraProviders extends FlexibleBridgingProvider[] = []>
3643
3899
  * as the bridge method but stops before execution.
3644
3900
  * @param params - The bridge parameters for cost estimation
3645
3901
  * @returns Promise resolving to detailed cost breakdown including gas estimates
3646
- * @throws {ValidationError} When the parameters are invalid.
3902
+ * @throws {KitError} When the parameters are invalid.
3647
3903
  * @throws {UnsupportedRouteError} When the route is not supported.
3648
3904
  *
3649
3905
  * @example
@@ -3728,40 +3984,61 @@ declare class BridgeKit<TExtraProviders extends FlexibleBridgingProvider[] = []>
3728
3984
  */
3729
3985
  private mergeCustomFeeConfig;
3730
3986
  /**
3731
- * Sets the custom fee policy for the kit.
3987
+ * Resolve the custom fee for a bridge transfer.
3732
3988
  *
3733
- * Ensures the fee is represented in the smallest unit of the token.
3734
- * - If the token is USDC, the fee is converted to base units (6 decimals).
3735
- * - If the token is not USDC, the fee is returned as is.
3989
+ * Checks which fee function the user provided and executes accordingly:
3990
+ * - `computeFee`: receives human-readable amounts, returns human-readable fee
3991
+ * - `calculateFee` (deprecated): receives smallest units, returns smallest units
3992
+ *
3993
+ * @param providerParams - The resolved bridge parameters (amounts in smallest units).
3994
+ * @returns The resolved fee in smallest units, or undefined if no fee policy is set.
3995
+ */
3996
+ private resolveFee;
3997
+ /**
3998
+ * Set the custom fee policy for the kit.
3736
3999
  *
3737
- * This allows developers to specify the kit-level fee in base units (e.g., USDC: 1, ETH: 0.000001),
3738
- * and the kit will handle conversion to the smallest unit as needed.
4000
+ * Use `computeFee` (recommended) for human-readable amounts, or `calculateFee`
4001
+ * (deprecated) for smallest-unit amounts. Only one should be provided.
4002
+ *
4003
+ * ```text
4004
+ * Transfer amount (user input, e.g., 1,000 USDC)
4005
+ * ↓ Wallet signs for transfer + custom fee (e.g., 1,000 + 10 = 1,010 USDC)
4006
+ * ↓ Custom fee split (10% Circle, 90% your recipientAddress wallet)
4007
+ * ↓ Full transfer amount (1,000 USDC) forwarded to CCTPv2
4008
+ * ↓ CCTPv2 protocol fee (e.g., 0.1 USDC) deducted from transfer amount
4009
+ * ↓ User receives funds on destination chain (e.g., 999.9 USDC)
4010
+ * ```
3739
4011
  *
3740
4012
  * @param customFeePolicy - The custom fee policy to set.
3741
- * @throws {ValidationError} If the custom fee policy is invalid or missing required functions
4013
+ * @throws {KitError} If the custom fee policy is invalid or missing required functions
3742
4014
  *
3743
4015
  * @example
3744
4016
  * ```typescript
3745
4017
  * import { BridgeKit } from '@circle-fin/bridge-kit'
3746
- * import { Blockchain } from '@core/chains'
3747
4018
  *
3748
4019
  * const kit = new BridgeKit()
3749
4020
  *
3750
4021
  * kit.setCustomFeePolicy({
3751
- * calculateFee: (params) => {
3752
- * // Return decimal string - kit converts to smallest units automatically
3753
- * // '0.1' becomes '100000' (0.1 USDC with 6 decimals)
3754
- * return params.source.chain.chain === Blockchain.Ethereum_Sepolia
3755
- * ? '0.1' // 0.1 USDC
3756
- * : '0.2'; // 0.2 USDC
4022
+ * // computeFee receives human-readable amounts (e.g., '100' for 100 USDC)
4023
+ * computeFee: (params) => {
4024
+ * const amount = parseFloat(params.amount)
4025
+ *
4026
+ * // 1% fee, bounded to 5-50 USDC
4027
+ * const fee = Math.min(Math.max(amount * 0.01, 5), 50)
4028
+ * return fee.toFixed(6)
3757
4029
  * },
3758
- * resolveFeeRecipientAddress: (feePayoutChain, params) => {
3759
- * // Return valid address for the source chain
3760
- * return params.source.chain.chain === Blockchain.Ethereum_Sepolia
3761
- * ? '0x23f9a5BEA7B92a0638520607407BC7f0310aEeD4'
3762
- * : '0x1E1A18B7bD95bcFcFb4d6E245D289C1e95547b35';
4030
+ * resolveFeeRecipientAddress: (feePayoutChain) => {
4031
+ * return feePayoutChain.type === 'solana'
4032
+ * ? '9xQeWvG816bUx9EP9MnZ4buHh3A6E2dFQa4Xz6V7C7Gn'
4033
+ * : '0x23f9a5BEA7B92a0638520607407BC7f0310aEeD4'
3763
4034
  * },
3764
- * });
4035
+ * })
4036
+ *
4037
+ * // 100 USDC transfer + 5 USDC custom fee results:
4038
+ * // - Wallet signs for 105 USDC total.
4039
+ * // - Circle receives 0.5 USDC (10% share of the custom fee).
4040
+ * // - Your recipientAddress wallet receives 4.5 USDC.
4041
+ * // - CCTPv2 processes 100 USDC and later deducts its own protocol fee.
3765
4042
  * ```
3766
4043
  */
3767
4044
  setCustomFeePolicy(customFeePolicy: CustomFeePolicy): void;
@@ -4061,6 +4338,15 @@ declare const RECOVERABILITY_VALUES: readonly ["RETRYABLE", "RESUMABLE", "FATAL"
4061
4338
  * - RESUMABLE errors are returned when a flow fails mid-execution but can be continued
4062
4339
  */
4063
4340
  type Recoverability = (typeof RECOVERABILITY_VALUES)[number];
4341
+ /**
4342
+ * Array of valid error type values for validation.
4343
+ * Derived from ERROR_TYPES const object.
4344
+ */
4345
+ declare const ERROR_TYPE_VALUES: ("INPUT" | "BALANCE" | "ONCHAIN" | "RPC" | "NETWORK")[];
4346
+ /**
4347
+ * Error type indicating the category of the error.
4348
+ */
4349
+ type ErrorType = (typeof ERROR_TYPE_VALUES)[number];
4064
4350
  /**
4065
4351
  * Structured error details with consistent properties for programmatic handling.
4066
4352
  *
@@ -4072,7 +4358,8 @@ type Recoverability = (typeof RECOVERABILITY_VALUES)[number];
4072
4358
  * ```typescript
4073
4359
  * const error: ErrorDetails = {
4074
4360
  * code: 1001,
4075
- * name: "NETWORK_MISMATCH",
4361
+ * name: "INPUT_NETWORK_MISMATCH",
4362
+ * type: "INPUT",
4076
4363
  * recoverability: "FATAL",
4077
4364
  * message: "Source and destination networks must be different",
4078
4365
  * cause: {
@@ -4080,15 +4367,31 @@ type Recoverability = (typeof RECOVERABILITY_VALUES)[number];
4080
4367
  * }
4081
4368
  * }
4082
4369
  * ```
4370
+ *
4371
+ * @example
4372
+ * ```typescript
4373
+ * const error: ErrorDetails = {
4374
+ * code: 9001,
4375
+ * name: "BALANCE_INSUFFICIENT_TOKEN",
4376
+ * type: "BALANCE",
4377
+ * recoverability: "FATAL",
4378
+ * message: "Insufficient USDC balance on Ethereum",
4379
+ * cause: {
4380
+ * trace: { token: "USDC", chain: "Ethereum" }
4381
+ * }
4382
+ * }
4383
+ * ```
4083
4384
  */
4084
4385
  interface ErrorDetails {
4085
- /** Numeric identifier following standardized ranges (1000+ for INPUT errors) */
4386
+ /** Numeric identifier following standardized ranges (see error code registry) */
4086
4387
  code: number;
4087
- /** Human-readable ID (e.g., "NETWORK_MISMATCH") */
4388
+ /** Human-readable ID (e.g., "INPUT_NETWORK_MISMATCH", "BALANCE_INSUFFICIENT_TOKEN") */
4088
4389
  name: string;
4390
+ /** Error category indicating where the error originated */
4391
+ type: ErrorType;
4089
4392
  /** Error handling strategy */
4090
4393
  recoverability: Recoverability;
4091
- /** User-friendly explanation with network context */
4394
+ /** User-friendly explanation with context */
4092
4395
  message: string;
4093
4396
  /** Raw error details, context, or the original error that caused this one. */
4094
4397
  cause?: {
@@ -4145,6 +4448,8 @@ declare class KitError extends Error implements ErrorDetails {
4145
4448
  readonly code: number;
4146
4449
  /** Human-readable ID (e.g., "NETWORK_MISMATCH") */
4147
4450
  readonly name: string;
4451
+ /** Error category indicating where the error originated */
4452
+ readonly type: ErrorType;
4148
4453
  /** Error handling strategy */
4149
4454
  readonly recoverability: Recoverability;
4150
4455
  /** Raw error details, context, or the original error that caused this one. */
@@ -4239,31 +4544,25 @@ declare function isFatalError(error: unknown): boolean;
4239
4544
  */
4240
4545
  declare function isRetryableError(error: unknown): boolean;
4241
4546
  /**
4242
- * Combined type guard to check if error is KitError with INPUT type.
4547
+ * Type guard to check if error is KitError with INPUT type.
4243
4548
  *
4244
- * INPUT errors have error codes in the 1000-1099 range and represent
4245
- * validation failures, invalid parameters, or user input problems.
4246
- * These errors are always FATAL and require the user to correct their
4247
- * input before retrying.
4549
+ * INPUT errors represent validation failures, invalid parameters,
4550
+ * or user input problems. These errors are always FATAL and require
4551
+ * the user to correct their input before retrying.
4248
4552
  *
4249
4553
  * @param error - Unknown error to check
4250
- * @returns True if error is KitError with INPUT error code range
4554
+ * @returns True if error is KitError with INPUT type
4251
4555
  *
4252
4556
  * @example
4253
4557
  * ```typescript
4254
4558
  * import { isInputError } from '@core/errors'
4255
- * import { createBridgeKit } from '@core/bridge'
4256
4559
  *
4257
- * async function handleBridge() {
4258
- * const kit = createBridgeKit(config)
4259
- * const params = { amount: '100', from: 'ethereum', to: 'polygon' }
4260
- *
4261
- * try {
4262
- * await kit.bridge(params)
4263
- * } catch (error) {
4264
- * if (isInputError(error)) {
4265
- * console.log(`Input error: ${error.message} (code: ${error.code})`)
4266
- * }
4560
+ * try {
4561
+ * await kit.bridge(params)
4562
+ * } catch (error) {
4563
+ * if (isInputError(error)) {
4564
+ * console.log('Validation error:', error.message)
4565
+ * showValidationUI()
4267
4566
  * }
4268
4567
  * }
4269
4568
  * ```
@@ -4320,5 +4619,5 @@ declare function getErrorMessage(error: unknown): string;
4320
4619
  */
4321
4620
  declare function getErrorCode(error: unknown): number | null;
4322
4621
 
4323
- export { Blockchain, BridgeKit, KitError, TransferSpeed, bridgeParamsWithChainIdentifierSchema, getErrorCode, getErrorMessage, isFatalError, isInputError, isKitError, isRetryableError, setExternalPrefix };
4324
- export type { ActionHandler, AdapterContext, BridgeConfig, BridgeKitConfig, BridgeParams, BridgeResult, ChainDefinition, ChainIdentifier, CustomFeePolicy, ErrorDetails, Recoverability };
4622
+ export { Blockchain, BridgeChain, BridgeKit, KitError, TransferSpeed, bridgeParamsWithChainIdentifierSchema, getErrorCode, getErrorMessage, isFatalError, isInputError, isKitError, isRetryableError, resolveChainIdentifier, setExternalPrefix };
4623
+ export type { ActionHandler, AdapterContext, BridgeChainIdentifier, BridgeConfig, BridgeKitConfig, BridgeParams, BridgeResult, ChainDefinition, ChainIdentifier, CustomFeePolicy, ErrorDetails, EstimateResult, Recoverability };