@circle-fin/provider-cctp-v2 1.8.2 → 1.8.3

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,11 @@
1
1
  # @circle-fin/provider-cctp-v2
2
2
 
3
+ ## 1.8.3
4
+
5
+ ### Patch Changes
6
+
7
+ - `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.
8
+
3
9
  ## 1.8.2
4
10
 
5
11
  ### Patch Changes
package/index.cjs CHANGED
@@ -6391,7 +6391,8 @@ const DEFAULT_RETRYABLE_ERROR_CODES = [
6391
6391
  *
6392
6392
  * @remarks
6393
6393
  * Check order for KitError instances:
6394
- * 1. If `recoverability === 'RETRYABLE'`, return `true` immediately (priority check).
6394
+ * 1. If `recoverability === 'RETRYABLE'` or `recoverability === 'RESUMABLE'`,
6395
+ * return `true` immediately (priority check).
6395
6396
  * 2. Otherwise, check if `error.code` is in `DEFAULT_RETRYABLE_ERROR_CODES` (fallback check).
6396
6397
  * 3. Non-KitError instances always return `false`.
6397
6398
  *
@@ -6402,6 +6403,12 @@ const DEFAULT_RETRYABLE_ERROR_CODES = [
6402
6403
  * subsequent attempts, such as network timeouts or temporary service
6403
6404
  * unavailability. These errors are safe to retry after a delay.
6404
6405
  *
6406
+ * RESUMABLE errors indicate a multi-phase operation that completed some phases
6407
+ * before failing (for example, a token approval landed but the execution
6408
+ * transaction failed). They are also retryable — re-running the operation is
6409
+ * safe — but callers that have a kit-level `retry()` should prefer it so that
6410
+ * already-completed phases are skipped.
6411
+ *
6405
6412
  * @param error - Unknown error to check
6406
6413
  * @returns True if error is retryable
6407
6414
  *
@@ -6447,16 +6454,29 @@ const DEFAULT_RETRYABLE_ERROR_CODES = [
6447
6454
  * })
6448
6455
  * isRetryableError(error3) // false
6449
6456
  *
6457
+ * // KitError with RESUMABLE recoverability (partially-completed operation)
6458
+ * const error4 = new KitError({
6459
+ * code: 8101,
6460
+ * name: 'EARN_EXECUTION_FAILED',
6461
+ * type: 'SERVICE',
6462
+ * recoverability: 'RESUMABLE',
6463
+ * message: 'Execution failed after approval',
6464
+ * })
6465
+ * isRetryableError(error4) // true
6466
+ *
6450
6467
  * // Non-KitError
6451
- * const error4 = new Error('Standard error')
6452
- * isRetryableError(error4) // false
6468
+ * const error5 = new Error('Standard error')
6469
+ * isRetryableError(error5) // false
6453
6470
  * ```
6454
6471
  */
6455
6472
  function isRetryableError$1(error) {
6456
6473
  // Use proper type guard to check if it's a KitError
6457
6474
  if (isKitError(error)) {
6458
- // Priority check: explicit recoverability
6459
- if (error.recoverability === 'RETRYABLE') {
6475
+ // Priority check: explicit recoverability. RESUMABLE errors are a subset of
6476
+ // retryable errors re-running the operation is safe, but a kit-level
6477
+ // retry() can resume from the failed phase instead.
6478
+ if (error.recoverability === 'RETRYABLE' ||
6479
+ error.recoverability === 'RESUMABLE') {
6460
6480
  return true;
6461
6481
  }
6462
6482
  // Fallback check: error code against default retryable codes
@@ -12246,7 +12266,7 @@ async function buildBatchedStep(name, receipt, batchId, adapter, chain, statusCo
12246
12266
  return step;
12247
12267
  }
12248
12268
 
12249
- var version = "1.8.2";
12269
+ var version = "1.8.3";
12250
12270
  var pkg = {
12251
12271
  version: version};
12252
12272
 
@@ -12852,60 +12872,6 @@ const validateBalanceForTransaction = async (params) => {
12852
12872
  }
12853
12873
  };
12854
12874
 
12855
- /**
12856
- * Validate that the adapter has sufficient native token balance for transaction fees.
12857
- *
12858
- * This function checks if the adapter's current native token balance (ETH, SOL, etc.)
12859
- * is greater than zero. It throws a KitError with code 9002 (BALANCE_INSUFFICIENT_GAS)
12860
- * if the balance is zero, indicating the wallet cannot pay for transaction fees.
12861
- *
12862
- * @param params - The validation parameters containing adapter and operation context.
12863
- * @returns A promise that resolves to void if validation passes.
12864
- * @throws {KitError} When the adapter's native balance is zero (code: 9002).
12865
- *
12866
- * @example
12867
- * ```typescript
12868
- * import { validateNativeBalanceForTransaction } from '@core/adapter'
12869
- * import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
12870
- * import { isKitError, ERROR_TYPES } from '@core/errors'
12871
- *
12872
- * const adapter = createViemAdapterFromPrivateKey({
12873
- * privateKey: '0x...',
12874
- * chain: 'Ethereum',
12875
- * })
12876
- *
12877
- * try {
12878
- * await validateNativeBalanceForTransaction({
12879
- * adapter,
12880
- * operationContext: { chain: 'Ethereum' },
12881
- * })
12882
- * console.log('Native balance validation passed')
12883
- * } catch (error) {
12884
- * if (isKitError(error) && error.type === ERROR_TYPES.BALANCE) {
12885
- * console.error('Insufficient gas funds:', error.message)
12886
- * }
12887
- * }
12888
- * ```
12889
- */
12890
- const validateNativeBalanceForTransaction = async (params) => {
12891
- const { adapter, operationContext } = params;
12892
- const balancePrepared = await adapter.prepareAction('native.balanceOf', {
12893
- walletAddress: operationContext.address,
12894
- }, operationContext);
12895
- const balance = await balancePrepared.execute();
12896
- if (BigInt(balance) === 0n) {
12897
- const { chain } = operationContext;
12898
- const chainName = extractChainInfo(chain).name;
12899
- const nativeSymbol = typeof chain === 'object' && chain !== null && 'nativeCurrency' in chain
12900
- ? chain.nativeCurrency.symbol
12901
- : undefined;
12902
- throw createInsufficientGasError(chainName, nativeSymbol, {
12903
- balance: '0',
12904
- walletAddress: operationContext.address,
12905
- });
12906
- }
12907
- };
12908
-
12909
12875
  /**
12910
12876
  * Permit signature standards for gasless token approvals.
12911
12877
  *
@@ -13466,7 +13432,7 @@ class CCTPV2BridgingProvider extends BridgingProvider {
13466
13432
  async bridge(params) {
13467
13433
  // CCTP-specific bridge params validation (includes base validation)
13468
13434
  assertCCTPv2BridgeParams(params);
13469
- const { source, destination, amount, token } = params;
13435
+ const { source, amount, token } = params;
13470
13436
  // Extract operation context from source wallet context for balance validation
13471
13437
  const sourceOperationContext = this.extractOperationContext(source);
13472
13438
  // Validate USDC balance for transaction on source chain
@@ -13477,24 +13443,6 @@ class CCTPV2BridgingProvider extends BridgingProvider {
13477
13443
  tokenAddress: source.chain.usdcAddress,
13478
13444
  operationContext: sourceOperationContext,
13479
13445
  });
13480
- // Validate native balance > 0 for gas fees on source chain
13481
- await validateNativeBalanceForTransaction({
13482
- adapter: source.adapter,
13483
- operationContext: sourceOperationContext,
13484
- });
13485
- // Only validate destination native balance if there's an adapter
13486
- // and forwarder is not being used (forwarder handles mint, no gas needed)
13487
- if ('adapter' in destination &&
13488
- destination.adapter &&
13489
- !destination.useForwarder) {
13490
- // Extract operation context from destination wallet context
13491
- const destinationOperationContext = this.extractOperationContext(destination);
13492
- // Validate native balance > 0 for gas fees on destination chain
13493
- await validateNativeBalanceForTransaction({
13494
- adapter: destination.adapter,
13495
- operationContext: destinationOperationContext,
13496
- });
13497
- }
13498
13446
  return bridge(params, this);
13499
13447
  }
13500
13448
  /**
package/index.mjs CHANGED
@@ -6384,7 +6384,8 @@ const DEFAULT_RETRYABLE_ERROR_CODES = [
6384
6384
  *
6385
6385
  * @remarks
6386
6386
  * Check order for KitError instances:
6387
- * 1. If `recoverability === 'RETRYABLE'`, return `true` immediately (priority check).
6387
+ * 1. If `recoverability === 'RETRYABLE'` or `recoverability === 'RESUMABLE'`,
6388
+ * return `true` immediately (priority check).
6388
6389
  * 2. Otherwise, check if `error.code` is in `DEFAULT_RETRYABLE_ERROR_CODES` (fallback check).
6389
6390
  * 3. Non-KitError instances always return `false`.
6390
6391
  *
@@ -6395,6 +6396,12 @@ const DEFAULT_RETRYABLE_ERROR_CODES = [
6395
6396
  * subsequent attempts, such as network timeouts or temporary service
6396
6397
  * unavailability. These errors are safe to retry after a delay.
6397
6398
  *
6399
+ * RESUMABLE errors indicate a multi-phase operation that completed some phases
6400
+ * before failing (for example, a token approval landed but the execution
6401
+ * transaction failed). They are also retryable — re-running the operation is
6402
+ * safe — but callers that have a kit-level `retry()` should prefer it so that
6403
+ * already-completed phases are skipped.
6404
+ *
6398
6405
  * @param error - Unknown error to check
6399
6406
  * @returns True if error is retryable
6400
6407
  *
@@ -6440,16 +6447,29 @@ const DEFAULT_RETRYABLE_ERROR_CODES = [
6440
6447
  * })
6441
6448
  * isRetryableError(error3) // false
6442
6449
  *
6450
+ * // KitError with RESUMABLE recoverability (partially-completed operation)
6451
+ * const error4 = new KitError({
6452
+ * code: 8101,
6453
+ * name: 'EARN_EXECUTION_FAILED',
6454
+ * type: 'SERVICE',
6455
+ * recoverability: 'RESUMABLE',
6456
+ * message: 'Execution failed after approval',
6457
+ * })
6458
+ * isRetryableError(error4) // true
6459
+ *
6443
6460
  * // Non-KitError
6444
- * const error4 = new Error('Standard error')
6445
- * isRetryableError(error4) // false
6461
+ * const error5 = new Error('Standard error')
6462
+ * isRetryableError(error5) // false
6446
6463
  * ```
6447
6464
  */
6448
6465
  function isRetryableError$1(error) {
6449
6466
  // Use proper type guard to check if it's a KitError
6450
6467
  if (isKitError(error)) {
6451
- // Priority check: explicit recoverability
6452
- if (error.recoverability === 'RETRYABLE') {
6468
+ // Priority check: explicit recoverability. RESUMABLE errors are a subset of
6469
+ // retryable errors re-running the operation is safe, but a kit-level
6470
+ // retry() can resume from the failed phase instead.
6471
+ if (error.recoverability === 'RETRYABLE' ||
6472
+ error.recoverability === 'RESUMABLE') {
6453
6473
  return true;
6454
6474
  }
6455
6475
  // Fallback check: error code against default retryable codes
@@ -12239,7 +12259,7 @@ async function buildBatchedStep(name, receipt, batchId, adapter, chain, statusCo
12239
12259
  return step;
12240
12260
  }
12241
12261
 
12242
- var version = "1.8.2";
12262
+ var version = "1.8.3";
12243
12263
  var pkg = {
12244
12264
  version: version};
12245
12265
 
@@ -12845,60 +12865,6 @@ const validateBalanceForTransaction = async (params) => {
12845
12865
  }
12846
12866
  };
12847
12867
 
12848
- /**
12849
- * Validate that the adapter has sufficient native token balance for transaction fees.
12850
- *
12851
- * This function checks if the adapter's current native token balance (ETH, SOL, etc.)
12852
- * is greater than zero. It throws a KitError with code 9002 (BALANCE_INSUFFICIENT_GAS)
12853
- * if the balance is zero, indicating the wallet cannot pay for transaction fees.
12854
- *
12855
- * @param params - The validation parameters containing adapter and operation context.
12856
- * @returns A promise that resolves to void if validation passes.
12857
- * @throws {KitError} When the adapter's native balance is zero (code: 9002).
12858
- *
12859
- * @example
12860
- * ```typescript
12861
- * import { validateNativeBalanceForTransaction } from '@core/adapter'
12862
- * import { createViemAdapterFromPrivateKey } from '@circle-fin/adapter-viem-v2'
12863
- * import { isKitError, ERROR_TYPES } from '@core/errors'
12864
- *
12865
- * const adapter = createViemAdapterFromPrivateKey({
12866
- * privateKey: '0x...',
12867
- * chain: 'Ethereum',
12868
- * })
12869
- *
12870
- * try {
12871
- * await validateNativeBalanceForTransaction({
12872
- * adapter,
12873
- * operationContext: { chain: 'Ethereum' },
12874
- * })
12875
- * console.log('Native balance validation passed')
12876
- * } catch (error) {
12877
- * if (isKitError(error) && error.type === ERROR_TYPES.BALANCE) {
12878
- * console.error('Insufficient gas funds:', error.message)
12879
- * }
12880
- * }
12881
- * ```
12882
- */
12883
- const validateNativeBalanceForTransaction = async (params) => {
12884
- const { adapter, operationContext } = params;
12885
- const balancePrepared = await adapter.prepareAction('native.balanceOf', {
12886
- walletAddress: operationContext.address,
12887
- }, operationContext);
12888
- const balance = await balancePrepared.execute();
12889
- if (BigInt(balance) === 0n) {
12890
- const { chain } = operationContext;
12891
- const chainName = extractChainInfo(chain).name;
12892
- const nativeSymbol = typeof chain === 'object' && chain !== null && 'nativeCurrency' in chain
12893
- ? chain.nativeCurrency.symbol
12894
- : undefined;
12895
- throw createInsufficientGasError(chainName, nativeSymbol, {
12896
- balance: '0',
12897
- walletAddress: operationContext.address,
12898
- });
12899
- }
12900
- };
12901
-
12902
12868
  /**
12903
12869
  * Permit signature standards for gasless token approvals.
12904
12870
  *
@@ -13459,7 +13425,7 @@ class CCTPV2BridgingProvider extends BridgingProvider {
13459
13425
  async bridge(params) {
13460
13426
  // CCTP-specific bridge params validation (includes base validation)
13461
13427
  assertCCTPv2BridgeParams(params);
13462
- const { source, destination, amount, token } = params;
13428
+ const { source, amount, token } = params;
13463
13429
  // Extract operation context from source wallet context for balance validation
13464
13430
  const sourceOperationContext = this.extractOperationContext(source);
13465
13431
  // Validate USDC balance for transaction on source chain
@@ -13470,24 +13436,6 @@ class CCTPV2BridgingProvider extends BridgingProvider {
13470
13436
  tokenAddress: source.chain.usdcAddress,
13471
13437
  operationContext: sourceOperationContext,
13472
13438
  });
13473
- // Validate native balance > 0 for gas fees on source chain
13474
- await validateNativeBalanceForTransaction({
13475
- adapter: source.adapter,
13476
- operationContext: sourceOperationContext,
13477
- });
13478
- // Only validate destination native balance if there's an adapter
13479
- // and forwarder is not being used (forwarder handles mint, no gas needed)
13480
- if ('adapter' in destination &&
13481
- destination.adapter &&
13482
- !destination.useForwarder) {
13483
- // Extract operation context from destination wallet context
13484
- const destinationOperationContext = this.extractOperationContext(destination);
13485
- // Validate native balance > 0 for gas fees on destination chain
13486
- await validateNativeBalanceForTransaction({
13487
- adapter: destination.adapter,
13488
- operationContext: destinationOperationContext,
13489
- });
13490
- }
13491
13439
  return bridge(params, this);
13492
13440
  }
13493
13441
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@circle-fin/provider-cctp-v2",
3
- "version": "1.8.2",
3
+ "version": "1.8.3",
4
4
  "description": "Circle's official Cross-Chain Transfer Protocol v2 provider for native USDC bridging",
5
5
  "keywords": [
6
6
  "circle",