@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 +6 -0
- package/index.cjs +27 -79
- package/index.mjs +27 -79
- package/package.json +1 -1
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'
|
|
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
|
|
6452
|
-
* isRetryableError(
|
|
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
|
-
|
|
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.
|
|
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,
|
|
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'
|
|
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
|
|
6445
|
-
* isRetryableError(
|
|
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
|
-
|
|
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.
|
|
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,
|
|
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
|
/**
|