@circle-fin/bridge-kit 1.2.0 → 1.3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @circle-fin/bridge-kit
2
2
 
3
+ ## 1.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - **Enhanced bridge estimate response**: `EstimateResult` now includes `token`, `amount`, `source`, `destination` fields to provide complete transfer information alongside cost estimates.
8
+ - Export error handling utilities and constants.
9
+
10
+ New exports include:
11
+
12
+ - Error type guards: isKitError, isBalanceError, isOnchainError, isRpcError, isNetworkError, isRetryableError, isFatalError
13
+ - Error constants: BalanceError, OnchainError, RpcError, NetworkError, InputError
14
+ - Utility: getErrorCode, getErrorMessage
15
+
3
16
  ## 1.2.0
4
17
 
5
18
  ### Minor Changes
package/chains.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) 2025, Circle Internet Group, Inc. All rights reserved.
2
+ * Copyright (c) 2026, Circle Internet Group, Inc. All rights reserved.
3
3
  *
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  *
package/chains.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) 2025, Circle Internet Group, Inc. All rights reserved.
2
+ * Copyright (c) 2026, Circle Internet Group, Inc. All rights reserved.
3
3
  *
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  *
package/chains.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) 2025, Circle Internet Group, Inc. All rights reserved.
2
+ * Copyright (c) 2026, Circle Internet Group, Inc. All rights reserved.
3
3
  *
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  *
package/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright (c) 2025, Circle Internet Group, Inc. All rights reserved.
2
+ * Copyright (c) 2026, Circle Internet Group, Inc. All rights reserved.
3
3
  *
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  *
@@ -272,6 +272,40 @@ function validateErrorDetails(details) {
272
272
  * stays within KitError's constraints.
273
273
  */
274
274
  const MAX_MESSAGE_LENGTH = 950;
275
+ /**
276
+ * Standard error message for invalid amount format.
277
+ *
278
+ * The SDK enforces strict dot-decimal notation for amount values. This constant
279
+ * provides a consistent error message when users provide amounts with:
280
+ * - Comma decimals (e.g., "1,5")
281
+ * - Thousand separators (e.g., "1,000.50")
282
+ * - Non-numeric characters
283
+ * - Invalid format
284
+ */
285
+ const AMOUNT_FORMAT_ERROR_MESSAGE = 'Amount must be a numeric string with dot (.) as decimal separator (e.g., "10.5", "100"), with no thousand separators or comma decimals';
286
+ /**
287
+ * Error message for amounts that must be greater than zero.
288
+ */
289
+ const AMOUNT_GREATER_THAN_ZERO_MESSAGE = 'Amount must be greater than 0';
290
+ /**
291
+ * Error message for amounts exceeding maximum decimal places.
292
+ *
293
+ * USDC uses 6 decimal places, so amounts with more precision are invalid.
294
+ */
295
+ const AMOUNT_MAX_DECIMAL_PLACES_MESSAGE = 'Maximum supported decimal places: 6';
296
+ /**
297
+ * Error message for amounts that must be non-negative.
298
+ *
299
+ * Used when validating amounts that can be zero or positive but not negative.
300
+ */
301
+ const AMOUNT_NON_NEGATIVE_MESSAGE = 'Amount must be non-negative';
302
+ /**
303
+ * Error message for invalid maxFee format.
304
+ *
305
+ * Used when validating the maxFee configuration parameter. The maxFee can be zero
306
+ * or positive and must follow strict dot-decimal notation.
307
+ */
308
+ const MAX_FEE_FORMAT_ERROR_MESSAGE = 'maxFee must be a numeric string with dot (.) as decimal separator (e.g., "1", "0.5", ".5", "1.5"), with no thousand separators or comma decimals';
275
309
 
276
310
  /**
277
311
  * Structured error class for Stablecoin Kit operations.
@@ -455,6 +489,158 @@ const InputError = {
455
489
  type: 'INPUT',
456
490
  },
457
491
  };
492
+ /**
493
+ * Standardized error definitions for BALANCE type errors.
494
+ *
495
+ * BALANCE errors indicate insufficient funds or allowance issues
496
+ * that prevent transaction execution.
497
+ *
498
+ * @example
499
+ * ```typescript
500
+ * import { BalanceError } from '@core/errors'
501
+ *
502
+ * const error = new KitError({
503
+ * ...BalanceError.INSUFFICIENT_TOKEN,
504
+ * recoverability: 'FATAL',
505
+ * message: 'Insufficient USDC balance on Ethereum',
506
+ * cause: { trace: { required: '100', available: '50' } }
507
+ * })
508
+ * ```
509
+ */
510
+ const BalanceError = {
511
+ /** Insufficient token balance for transaction */
512
+ INSUFFICIENT_TOKEN: {
513
+ code: 9001,
514
+ name: 'BALANCE_INSUFFICIENT_TOKEN',
515
+ type: 'BALANCE',
516
+ },
517
+ /** Insufficient native token (ETH/SOL/etc) for gas fees */
518
+ INSUFFICIENT_GAS: {
519
+ code: 9002,
520
+ name: 'BALANCE_INSUFFICIENT_GAS',
521
+ type: 'BALANCE',
522
+ },
523
+ /** Insufficient allowance for token transfer */
524
+ INSUFFICIENT_ALLOWANCE: {
525
+ code: 9003,
526
+ name: 'BALANCE_INSUFFICIENT_ALLOWANCE',
527
+ type: 'BALANCE',
528
+ },
529
+ };
530
+ /**
531
+ * Standardized error definitions for ONCHAIN type errors.
532
+ *
533
+ * ONCHAIN errors occur during transaction execution, simulation,
534
+ * or interaction with smart contracts on the blockchain.
535
+ *
536
+ * @example
537
+ * ```typescript
538
+ * import { OnchainError } from '@core/errors'
539
+ *
540
+ * const error = new KitError({
541
+ * ...OnchainError.SIMULATION_FAILED,
542
+ * recoverability: 'FATAL',
543
+ * message: 'Simulation failed: ERC20 transfer amount exceeds balance',
544
+ * cause: { trace: { reason: 'ERC20: transfer amount exceeds balance' } }
545
+ * })
546
+ * ```
547
+ */
548
+ const OnchainError = {
549
+ /** Transaction reverted on-chain after execution */
550
+ TRANSACTION_REVERTED: {
551
+ code: 5001,
552
+ name: 'ONCHAIN_TRANSACTION_REVERTED',
553
+ type: 'ONCHAIN',
554
+ },
555
+ /** Pre-flight transaction simulation failed */
556
+ SIMULATION_FAILED: {
557
+ code: 5002,
558
+ name: 'ONCHAIN_SIMULATION_FAILED',
559
+ type: 'ONCHAIN',
560
+ },
561
+ /** Transaction ran out of gas during execution */
562
+ OUT_OF_GAS: {
563
+ code: 5003,
564
+ name: 'ONCHAIN_OUT_OF_GAS',
565
+ type: 'ONCHAIN',
566
+ },
567
+ /** Transaction exceeds block gas limit */
568
+ GAS_LIMIT_EXCEEDED: {
569
+ code: 5004,
570
+ name: 'ONCHAIN_GAS_LIMIT_EXCEEDED',
571
+ type: 'ONCHAIN',
572
+ },
573
+ };
574
+ /**
575
+ * Standardized error definitions for RPC type errors.
576
+ *
577
+ * RPC errors occur when communicating with blockchain RPC providers,
578
+ * including endpoint failures, invalid responses, and provider-specific issues.
579
+ *
580
+ * @example
581
+ * ```typescript
582
+ * import { RpcError } from '@core/errors'
583
+ *
584
+ * const error = new KitError({
585
+ * ...RpcError.ENDPOINT_ERROR,
586
+ * recoverability: 'RETRYABLE',
587
+ * message: 'RPC endpoint unavailable on Ethereum',
588
+ * cause: { trace: { endpoint: 'https://mainnet.infura.io' } }
589
+ * })
590
+ * ```
591
+ */
592
+ const RpcError = {
593
+ /** RPC endpoint returned error or is unavailable */
594
+ ENDPOINT_ERROR: {
595
+ code: 4001,
596
+ name: 'RPC_ENDPOINT_ERROR',
597
+ type: 'RPC',
598
+ },
599
+ /** Invalid or unexpected RPC response format */
600
+ INVALID_RESPONSE: {
601
+ code: 4002,
602
+ name: 'RPC_INVALID_RESPONSE',
603
+ type: 'RPC',
604
+ },
605
+ /** Nonce-related errors from RPC provider */
606
+ NONCE_ERROR: {
607
+ code: 4003,
608
+ name: 'RPC_NONCE_ERROR',
609
+ type: 'RPC',
610
+ },
611
+ };
612
+ /**
613
+ * Standardized error definitions for NETWORK type errors.
614
+ *
615
+ * NETWORK errors indicate connectivity issues at the network layer,
616
+ * including DNS failures, connection timeouts, and unreachable endpoints.
617
+ *
618
+ * @example
619
+ * ```typescript
620
+ * import { NetworkError } from '@core/errors'
621
+ *
622
+ * const error = new KitError({
623
+ * ...NetworkError.CONNECTION_FAILED,
624
+ * recoverability: 'RETRYABLE',
625
+ * message: 'Failed to connect to Ethereum network',
626
+ * cause: { trace: { error: 'ECONNREFUSED' } }
627
+ * })
628
+ * ```
629
+ */
630
+ const NetworkError = {
631
+ /** Network connection failed or unreachable */
632
+ CONNECTION_FAILED: {
633
+ code: 3001,
634
+ name: 'NETWORK_CONNECTION_FAILED',
635
+ type: 'NETWORK',
636
+ },
637
+ /** Network request timeout */
638
+ TIMEOUT: {
639
+ code: 3002,
640
+ name: 'NETWORK_TIMEOUT',
641
+ type: 'NETWORK',
642
+ },
643
+ };
458
644
 
459
645
  /**
460
646
  * Creates error for network type mismatch between source and destination.
@@ -3415,6 +3601,114 @@ function isRetryableError(error) {
3415
3601
  function isInputError(error) {
3416
3602
  return isKitError(error) && error.type === ERROR_TYPES.INPUT;
3417
3603
  }
3604
+ /**
3605
+ * Type guard to check if error is KitError with BALANCE type.
3606
+ *
3607
+ * BALANCE errors indicate insufficient funds or allowance issues
3608
+ * that prevent transaction execution. These errors are always FATAL
3609
+ * and require the user to add funds or approve more tokens.
3610
+ *
3611
+ * @param error - Unknown error to check
3612
+ * @returns True if error is KitError with BALANCE type
3613
+ *
3614
+ * @example
3615
+ * ```typescript
3616
+ * import { isBalanceError } from '@core/errors'
3617
+ *
3618
+ * try {
3619
+ * await kit.bridge(params)
3620
+ * } catch (error) {
3621
+ * if (isBalanceError(error)) {
3622
+ * console.log('Insufficient funds:', error.message)
3623
+ * showAddFundsUI()
3624
+ * }
3625
+ * }
3626
+ * ```
3627
+ */
3628
+ function isBalanceError(error) {
3629
+ return isKitError(error) && error.type === ERROR_TYPES.BALANCE;
3630
+ }
3631
+ /**
3632
+ * Type guard to check if error is KitError with ONCHAIN type.
3633
+ *
3634
+ * ONCHAIN errors occur during transaction execution or simulation,
3635
+ * including reverts, gas issues, and smart contract failures.
3636
+ * These errors are typically FATAL.
3637
+ *
3638
+ * @param error - Unknown error to check
3639
+ * @returns True if error is KitError with ONCHAIN type
3640
+ *
3641
+ * @example
3642
+ * ```typescript
3643
+ * import { isOnchainError } from '@core/errors'
3644
+ *
3645
+ * try {
3646
+ * await kit.bridge(params)
3647
+ * } catch (error) {
3648
+ * if (isOnchainError(error)) {
3649
+ * console.log('Transaction failed:', error.message)
3650
+ * showTransactionErrorUI()
3651
+ * }
3652
+ * }
3653
+ * ```
3654
+ */
3655
+ function isOnchainError(error) {
3656
+ return isKitError(error) && error.type === ERROR_TYPES.ONCHAIN;
3657
+ }
3658
+ /**
3659
+ * Type guard to check if error is KitError with RPC type.
3660
+ *
3661
+ * RPC errors occur when communicating with blockchain RPC providers.
3662
+ * These errors are typically RETRYABLE as they often indicate
3663
+ * temporary provider issues.
3664
+ *
3665
+ * @param error - Unknown error to check
3666
+ * @returns True if error is KitError with RPC type
3667
+ *
3668
+ * @example
3669
+ * ```typescript
3670
+ * import { isRpcError } from '@core/errors'
3671
+ *
3672
+ * try {
3673
+ * await kit.bridge(params)
3674
+ * } catch (error) {
3675
+ * if (isRpcError(error)) {
3676
+ * console.log('RPC error:', error.message)
3677
+ * retryWithBackoff()
3678
+ * }
3679
+ * }
3680
+ * ```
3681
+ */
3682
+ function isRpcError(error) {
3683
+ return isKitError(error) && error.type === ERROR_TYPES.RPC;
3684
+ }
3685
+ /**
3686
+ * Type guard to check if error is KitError with NETWORK type.
3687
+ *
3688
+ * NETWORK errors indicate connectivity issues at the network layer.
3689
+ * These errors are typically RETRYABLE as they often indicate
3690
+ * temporary network problems.
3691
+ *
3692
+ * @param error - Unknown error to check
3693
+ * @returns True if error is KitError with NETWORK type
3694
+ *
3695
+ * @example
3696
+ * ```typescript
3697
+ * import { isNetworkError } from '@core/errors'
3698
+ *
3699
+ * try {
3700
+ * await kit.bridge(params)
3701
+ * } catch (error) {
3702
+ * if (isNetworkError(error)) {
3703
+ * console.log('Network issue:', error.message)
3704
+ * retryWithBackoff()
3705
+ * }
3706
+ * }
3707
+ * ```
3708
+ */
3709
+ function isNetworkError(error) {
3710
+ return isKitError(error) && error.type === ERROR_TYPES.NETWORK;
3711
+ }
3418
3712
  /**
3419
3713
  * Safely extracts error message from any error type.
3420
3714
  *
@@ -3704,7 +3998,6 @@ function convertZodErrorToStructured(zodError, params) {
3704
3998
  function createValidationFailedError(zodError) {
3705
3999
  return createValidationErrorFromZod(zodError, 'parameters');
3706
4000
  }
3707
- const AMOUNT_FORMAT_ERROR_MESSAGE = 'Amount must be a numeric string with dot (.) as decimal separator, with no thousand separators or comma decimals';
3708
4001
  /**
3709
4002
  * Handles amount-related validation errors from Zod.
3710
4003
  *
@@ -3754,7 +4047,7 @@ function handleAmountError(path, code, message, paramsObj) {
3754
4047
  */
3755
4048
  function handleNegativeAmountError(code, message, amount) {
3756
4049
  if (code === 'too_small' || message.includes('greater than')) {
3757
- return createInvalidAmountError(amount, 'Amount must be greater than 0');
4050
+ return createInvalidAmountError(amount, AMOUNT_GREATER_THAN_ZERO_MESSAGE);
3758
4051
  }
3759
4052
  return null;
3760
4053
  }
@@ -3776,10 +4069,10 @@ function handleCustomAmountError(code, message, amount) {
3776
4069
  if (code !== 'custom')
3777
4070
  return null;
3778
4071
  if (message.includes('non-negative')) {
3779
- return createInvalidAmountError(amount, 'Amount must be non-negative');
4072
+ return createInvalidAmountError(amount, AMOUNT_NON_NEGATIVE_MESSAGE);
3780
4073
  }
3781
4074
  if (message.includes('greater than 0')) {
3782
- return createInvalidAmountError(amount, 'Amount must be greater than 0');
4075
+ return createInvalidAmountError(amount, AMOUNT_GREATER_THAN_ZERO_MESSAGE);
3783
4076
  }
3784
4077
  if (message.includes('decimal places')) {
3785
4078
  return createInvalidAmountError(amount, message);
@@ -3812,7 +4105,7 @@ function handleInvalidStringAmountError(code, message, amount) {
3812
4105
  return null;
3813
4106
  // Check for decimal places validation
3814
4107
  if (isDecimalPlacesError(message)) {
3815
- return createInvalidAmountError(amount, 'Maximum supported decimal places: 6');
4108
+ return createInvalidAmountError(amount, AMOUNT_MAX_DECIMAL_PLACES_MESSAGE);
3816
4109
  }
3817
4110
  // Check for numeric format validation
3818
4111
  if (isNumericFormatError(message)) {
@@ -4337,7 +4630,7 @@ const parseAmount = (params) => {
4337
4630
  };
4338
4631
 
4339
4632
  var name = "@circle-fin/bridge-kit";
4340
- var version = "1.2.0";
4633
+ var version = "1.3.0";
4341
4634
  var pkg = {
4342
4635
  name: name,
4343
4636
  version: version};
@@ -4703,41 +4996,46 @@ exports.TransferSpeed = void 0;
4703
4996
  * - regexMessage: error message when the basic numeric format fails.
4704
4997
  * - maxDecimals: maximum number of decimal places allowed (e.g., 6 for USDC).
4705
4998
  */
4706
- const createDecimalStringValidator = (options) => (schema) => schema
4707
- .regex(/^-?(?:\d+(?:\.\d+)?|\.\d+)$/, options.regexMessage)
4708
- .superRefine((val, ctx) => {
4709
- const amount = Number.parseFloat(val);
4710
- if (Number.isNaN(amount)) {
4711
- ctx.addIssue({
4712
- code: zod.z.ZodIssueCode.custom,
4713
- message: options.regexMessage,
4714
- });
4715
- return;
4716
- }
4717
- // Check decimal precision if maxDecimals is specified
4718
- if (options.maxDecimals !== undefined) {
4719
- const decimalPart = val.split('.')[1];
4720
- if (decimalPart && decimalPart.length > options.maxDecimals) {
4999
+ const createDecimalStringValidator = (options) => (schema) => {
5000
+ // Capitalize first letter of attribute name for error messages
5001
+ const capitalizedAttributeName = options.attributeName.charAt(0).toUpperCase() +
5002
+ options.attributeName.slice(1);
5003
+ return schema
5004
+ .regex(/^-?(?:\d+(?:\.\d+)?|\.\d+)$/, options.regexMessage)
5005
+ .superRefine((val, ctx) => {
5006
+ const amount = Number.parseFloat(val);
5007
+ if (Number.isNaN(amount)) {
4721
5008
  ctx.addIssue({
4722
5009
  code: zod.z.ZodIssueCode.custom,
4723
- message: `Maximum supported decimal places: ${options.maxDecimals.toString()}`,
5010
+ message: options.regexMessage,
4724
5011
  });
4725
5012
  return;
4726
5013
  }
4727
- }
4728
- if (options.allowZero && amount < 0) {
4729
- ctx.addIssue({
4730
- code: zod.z.ZodIssueCode.custom,
4731
- message: `${options.attributeName} must be non-negative`,
4732
- });
4733
- }
4734
- else if (!options.allowZero && amount <= 0) {
4735
- ctx.addIssue({
4736
- code: zod.z.ZodIssueCode.custom,
4737
- message: `${options.attributeName} must be greater than 0`,
4738
- });
4739
- }
4740
- });
5014
+ // Check decimal precision if maxDecimals is specified
5015
+ if (options.maxDecimals !== undefined) {
5016
+ const decimalPart = val.split('.')[1];
5017
+ if (decimalPart && decimalPart.length > options.maxDecimals) {
5018
+ ctx.addIssue({
5019
+ code: zod.z.ZodIssueCode.custom,
5020
+ message: `Maximum supported decimal places: ${options.maxDecimals.toString()}`,
5021
+ });
5022
+ return;
5023
+ }
5024
+ }
5025
+ if (options.allowZero && amount < 0) {
5026
+ ctx.addIssue({
5027
+ code: zod.z.ZodIssueCode.custom,
5028
+ message: `${capitalizedAttributeName} must be non-negative`,
5029
+ });
5030
+ }
5031
+ else if (!options.allowZero && amount <= 0) {
5032
+ ctx.addIssue({
5033
+ code: zod.z.ZodIssueCode.custom,
5034
+ message: `${capitalizedAttributeName} must be greater than 0`,
5035
+ });
5036
+ }
5037
+ });
5038
+ };
4741
5039
  /**
4742
5040
  * Schema for validating chain definitions.
4743
5041
  * This ensures the basic structure of a chain definition is valid.
@@ -4897,7 +5195,7 @@ zod.z.object({
4897
5195
  .min(1, 'Required')
4898
5196
  .pipe(createDecimalStringValidator({
4899
5197
  allowZero: false,
4900
- regexMessage: 'Amount must be a numeric string with dot (.) as decimal separator (e.g., "0.1", ".1", "10.5", "1000.50"), with no thousand separators or comma decimals.',
5198
+ regexMessage: AMOUNT_FORMAT_ERROR_MESSAGE,
4901
5199
  attributeName: 'amount',
4902
5200
  maxDecimals: 6,
4903
5201
  })(zod.z.string())),
@@ -4910,7 +5208,7 @@ zod.z.object({
4910
5208
  .string()
4911
5209
  .pipe(createDecimalStringValidator({
4912
5210
  allowZero: true,
4913
- regexMessage: 'maxFee must be a numeric string with dot (.) as decimal separator (e.g., "1", "0.5", ".5", "1.5"), with no thousand separators or comma decimals.',
5211
+ regexMessage: MAX_FEE_FORMAT_ERROR_MESSAGE,
4914
5212
  attributeName: 'maxFee',
4915
5213
  maxDecimals: 6,
4916
5214
  })(zod.z.string()))
@@ -4919,11 +5217,6 @@ zod.z.object({
4919
5217
  }),
4920
5218
  });
4921
5219
 
4922
- /**
4923
- * Error message constants for validation
4924
- */
4925
- const AMOUNT_VALIDATION_MESSAGE = 'Amount must be a numeric string with dot (.) as decimal separator (e.g., "0.1", ".1", "10.5", "1000.50"), with no thousand separators or comma decimals.';
4926
- const MAX_FEE_VALIDATION_MESSAGE = 'maxFee must be a numeric string with dot (.) as decimal separator (e.g., "1", "0.5", ".5", "1.5"), with no thousand separators or comma decimals.';
4927
5220
  /**
4928
5221
  * Schema for validating AdapterContext for bridge operations.
4929
5222
  * Must always contain both adapter and chain explicitly.
@@ -5018,7 +5311,7 @@ const bridgeParamsWithChainIdentifierSchema = zod.z.object({
5018
5311
  .min(1, 'Required')
5019
5312
  .pipe(createDecimalStringValidator({
5020
5313
  allowZero: false,
5021
- regexMessage: AMOUNT_VALIDATION_MESSAGE,
5314
+ regexMessage: AMOUNT_FORMAT_ERROR_MESSAGE,
5022
5315
  attributeName: 'amount',
5023
5316
  maxDecimals: 6,
5024
5317
  })(zod.z.string())),
@@ -5031,7 +5324,7 @@ const bridgeParamsWithChainIdentifierSchema = zod.z.object({
5031
5324
  .min(1, 'Required')
5032
5325
  .pipe(createDecimalStringValidator({
5033
5326
  allowZero: true,
5034
- regexMessage: MAX_FEE_VALIDATION_MESSAGE,
5327
+ regexMessage: MAX_FEE_FORMAT_ERROR_MESSAGE,
5035
5328
  attributeName: 'maxFee',
5036
5329
  maxDecimals: 6,
5037
5330
  })(zod.z.string()))
@@ -5292,6 +5585,8 @@ const getAmountTransformer = (formatDirection) => formatDirection === 'to-human-
5292
5585
  : (params) => parseAmount(params).toString();
5293
5586
  /**
5294
5587
  * Format the bridge result into human-readable string values for the user or bigint string values for internal use.
5588
+ *
5589
+ * @typeParam T - The specific result type (must extend BridgeResult or EstimateResult). Preserves the exact type passed in.
5295
5590
  * @param result - The bridge result to format.
5296
5591
  * @param formatDirection - The direction to format the result in.
5297
5592
  * - If 'to-human-readable', the result will be converted to human-readable string values.
@@ -5321,7 +5616,9 @@ const formatBridgeResult = (result, formatDirection) => {
5321
5616
  return {
5322
5617
  ...result,
5323
5618
  amount: transform({ value: result.amount, token: result.token }),
5324
- ...(result.config && {
5619
+ ...('config' in result &&
5620
+ result.config &&
5621
+ Object.keys(result.config).length > 0 && {
5325
5622
  config: {
5326
5623
  ...result.config,
5327
5624
  ...(result.config.maxFee && {
@@ -5333,12 +5630,12 @@ const formatBridgeResult = (result, formatDirection) => {
5333
5630
  ...(result.config.customFee && {
5334
5631
  customFee: {
5335
5632
  ...result.config.customFee,
5336
- value: result.config.customFee.value
5337
- ? transform({
5633
+ ...(result.config.customFee.value && {
5634
+ value: transform({
5338
5635
  value: result.config.customFee.value,
5339
5636
  token: result.token,
5340
- })
5341
- : undefined,
5637
+ }),
5638
+ }),
5342
5639
  },
5343
5640
  }),
5344
5641
  },
@@ -5606,8 +5903,8 @@ class BridgeKit {
5606
5903
  const finalResolvedParams = await this.mergeCustomFeeConfig(resolvedParams);
5607
5904
  // Find a provider that supports this route
5608
5905
  const provider = this.findProviderForRoute(finalResolvedParams);
5609
- // Estimate the transfer using the provider
5610
- return provider.estimate(finalResolvedParams);
5906
+ // Estimate the transfer using the provider and format amounts to human-readable strings
5907
+ return formatBridgeResult(await provider.estimate(finalResolvedParams), 'to-human-readable');
5611
5908
  }
5612
5909
  /**
5613
5910
  * Get all chains supported by any provider in the kit.
@@ -5826,15 +6123,24 @@ class BridgeKit {
5826
6123
  // Auto-register this kit for user agent tracking
5827
6124
  registerKit(`${pkg.name}/${pkg.version}`);
5828
6125
 
6126
+ exports.BalanceError = BalanceError;
5829
6127
  exports.BridgeKit = BridgeKit;
6128
+ exports.InputError = InputError;
5830
6129
  exports.KitError = KitError;
6130
+ exports.NetworkError = NetworkError;
6131
+ exports.OnchainError = OnchainError;
6132
+ exports.RpcError = RpcError;
5831
6133
  exports.bridgeParamsWithChainIdentifierSchema = bridgeParamsWithChainIdentifierSchema;
5832
6134
  exports.getErrorCode = getErrorCode;
5833
6135
  exports.getErrorMessage = getErrorMessage;
6136
+ exports.isBalanceError = isBalanceError;
5834
6137
  exports.isFatalError = isFatalError;
5835
6138
  exports.isInputError = isInputError;
5836
6139
  exports.isKitError = isKitError;
6140
+ exports.isNetworkError = isNetworkError;
6141
+ exports.isOnchainError = isOnchainError;
5837
6142
  exports.isRetryableError = isRetryableError;
6143
+ exports.isRpcError = isRpcError;
5838
6144
  exports.resolveChainIdentifier = resolveChainIdentifier;
5839
6145
  exports.setExternalPrefix = setExternalPrefix;
5840
6146
  //# sourceMappingURL=index.cjs.map