@circle-fin/provider-cctp-v2 1.9.0 → 1.10.1
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 +30 -0
- package/index.cjs +2869 -2422
- package/index.d.cts +806 -240
- package/index.d.mts +806 -240
- package/index.d.ts +806 -240
- package/index.mjs +2865 -2423
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -373,6 +373,14 @@ interface CCTPSplitConfig {
|
|
|
373
373
|
type: 'split';
|
|
374
374
|
tokenMessenger: string;
|
|
375
375
|
messageTransmitter: string;
|
|
376
|
+
/**
|
|
377
|
+
* Address of the `TokenMessengerWithFees` wrapper, when deployed on this chain.
|
|
378
|
+
*
|
|
379
|
+
* Optional. Present only on chains that support the prepaid FORWARD path
|
|
380
|
+
* (source-chain fee collection via `depositForBurnWithHookAndFees`). Resolve
|
|
381
|
+
* it with `resolveCCTPV2ContractAddress(chain, 'tokenMessengerWithFees')`.
|
|
382
|
+
*/
|
|
383
|
+
tokenMessengerWithFees?: string;
|
|
376
384
|
confirmations: number;
|
|
377
385
|
}
|
|
378
386
|
/**
|
|
@@ -393,6 +401,14 @@ interface CCTPSplitConfig {
|
|
|
393
401
|
interface CCTPMergedConfig {
|
|
394
402
|
type: 'merged';
|
|
395
403
|
contract: string;
|
|
404
|
+
/**
|
|
405
|
+
* Address of the `TokenMessengerWithFees` wrapper, when deployed on this chain.
|
|
406
|
+
*
|
|
407
|
+
* Optional. Present only on chains that support the prepaid FORWARD path
|
|
408
|
+
* (source-chain fee collection via `depositForBurnWithHookAndFees`). Resolve
|
|
409
|
+
* it with `resolveCCTPV2ContractAddress(chain, 'tokenMessengerWithFees')`.
|
|
410
|
+
*/
|
|
411
|
+
tokenMessengerWithFees?: string;
|
|
396
412
|
confirmations: number;
|
|
397
413
|
}
|
|
398
414
|
/**
|
|
@@ -527,6 +543,21 @@ interface GatewayV1Contracts {
|
|
|
527
543
|
* @example "0xabcdef1234567890abcdef1234567890abcdef12"
|
|
528
544
|
*/
|
|
529
545
|
minter: string;
|
|
546
|
+
/**
|
|
547
|
+
* The address of the `DepositForHandler` contract.
|
|
548
|
+
*
|
|
549
|
+
* @description Optional. The handler the GenericExecutor calls on this chain
|
|
550
|
+
* to run a fast cross-chain deposit into the {@link GatewayV1Contracts.wallet}.
|
|
551
|
+
* Present only on chains that are fast-deposit destinations; other Gateway
|
|
552
|
+
* chains omit it.
|
|
553
|
+
*
|
|
554
|
+
* Address format varies by blockchain:
|
|
555
|
+
* - EVM chains: 40-character hexadecimal with 0x prefix (e.g., "0x1234...")
|
|
556
|
+
* - Solana: Base58-encoded 32-byte address (e.g., "9WzDX...")
|
|
557
|
+
*
|
|
558
|
+
* @example "0xD05E7D2E7d30b92c5F17d7d0fC575fce231F1A48"
|
|
559
|
+
*/
|
|
560
|
+
depositForHandler?: string;
|
|
530
561
|
}
|
|
531
562
|
/**
|
|
532
563
|
* Versioned map of Gateway contract configurations.
|
|
@@ -1765,6 +1796,110 @@ interface CCTPv2ActionMap {
|
|
|
1765
1796
|
*/
|
|
1766
1797
|
hookData: string;
|
|
1767
1798
|
};
|
|
1799
|
+
/**
|
|
1800
|
+
* Initiate a prepaid cross-chain USDC transfer through the `TokenMessengerWithFees` wrapper.
|
|
1801
|
+
*
|
|
1802
|
+
* Burn USDC on the source chain while collecting all fees up front against a
|
|
1803
|
+
* signed quote. The wrapper collects the fee via `FeeManager`, then delegates
|
|
1804
|
+
* to the unmodified `TokenMessengerV2`. When `hookData` is provided (the
|
|
1805
|
+
* GenericExecutor FORWARD path) the wrapper's `depositForBurnWithHookAndFees`
|
|
1806
|
+
* contract method is used; otherwise `depositForBurnWithFees` is used.
|
|
1807
|
+
*
|
|
1808
|
+
* @remarks
|
|
1809
|
+
* SDK/contract naming: this SDK action is `depositForBurnWithFees` but, when a
|
|
1810
|
+
* `hookData` is present, it dispatches to the `depositForBurnWithHookAndFees`
|
|
1811
|
+
* contract method on `TokenMessengerWithFees` (NOT on `TokenMessengerV2`).
|
|
1812
|
+
*
|
|
1813
|
+
* Fee payment channel (must match the quote's `feeToken`):
|
|
1814
|
+
* - Native fee (`feeToken` is the zero address): exactly `feeTotalAmount` is
|
|
1815
|
+
* attached as `msg.value`.
|
|
1816
|
+
* - ERC-20 fee (e.g. USDC): no value is attached; the caller must first approve
|
|
1817
|
+
* the wrapper for `feeTotalAmount` (see the provider's fee approval helper).
|
|
1818
|
+
*
|
|
1819
|
+
* @remarks
|
|
1820
|
+
* Unlike `depositForBurn`, the `TokenMessengerWithFees` contract methods do NOT
|
|
1821
|
+
* take `maxFee` or `minFinalityThreshold` — fee and finality behavior are
|
|
1822
|
+
* derived from the signed quote — so those fields are omitted from this action.
|
|
1823
|
+
*
|
|
1824
|
+
* @example
|
|
1825
|
+
* ```typescript
|
|
1826
|
+
* await adapter.action('cctp.v2.depositForBurnWithFees', {
|
|
1827
|
+
* amount: BigInt('1000000'),
|
|
1828
|
+
* mintRecipient: executorAddress, // GenericExecutor (bytes32)
|
|
1829
|
+
* destinationCaller: executorAddress, // GenericExecutor (bytes32)
|
|
1830
|
+
* fromChain: ethereum,
|
|
1831
|
+
* toChain: arc,
|
|
1832
|
+
* hookData: geForwardHookData, // cctp-forward-wrapped GenericExecutor blob
|
|
1833
|
+
* claim: { signedQuote: '0x...', refundAddress: '0x...' },
|
|
1834
|
+
* feeToken: '0x0000000000000000000000000000000000000000', // native
|
|
1835
|
+
* feeTotalAmount: 3500000n,
|
|
1836
|
+
* })
|
|
1837
|
+
* ```
|
|
1838
|
+
*/
|
|
1839
|
+
depositForBurnWithFees: Omit<CCTPv2ActionMap['depositForBurn'], 'maxFee' | 'minFinalityThreshold'> & {
|
|
1840
|
+
/**
|
|
1841
|
+
* Optional hex-encoded hook data for the GenericExecutor FORWARD path.
|
|
1842
|
+
*
|
|
1843
|
+
* When present, the `depositForBurnWithHookAndFees` contract method is used
|
|
1844
|
+
* and the blob must be wrapped in the `cctp-forward` envelope (the wrapper
|
|
1845
|
+
* rejects a FORWARD fee quote whose hook lacks it). When omitted, the plain
|
|
1846
|
+
* `depositForBurnWithFees` contract method is used.
|
|
1847
|
+
*/
|
|
1848
|
+
hookData?: string;
|
|
1849
|
+
/**
|
|
1850
|
+
* Signed fee quote claim passed to the `TokenMessengerWithFees` wrapper.
|
|
1851
|
+
*
|
|
1852
|
+
* `signedQuote` is the `[uint8 0x01][abi.encode(Quote)]` blob returned by the
|
|
1853
|
+
* Fee Quote service; `refundAddress` receives any fee overpayment refund.
|
|
1854
|
+
*/
|
|
1855
|
+
claim: QuoteClaim;
|
|
1856
|
+
/**
|
|
1857
|
+
* Fee token from the signed quote.
|
|
1858
|
+
*
|
|
1859
|
+
* The zero address (`0x000…0`) means the fee is paid in native currency and
|
|
1860
|
+
* is attached as `msg.value`. Any other address (e.g. USDC) means an ERC-20
|
|
1861
|
+
* fee that must be approved to the wrapper beforehand. This is independent of
|
|
1862
|
+
* `burnToken`, which is always USDC.
|
|
1863
|
+
*/
|
|
1864
|
+
feeToken: string;
|
|
1865
|
+
/**
|
|
1866
|
+
* Total fee amount from the signed quote, in `feeToken` minor units.
|
|
1867
|
+
*
|
|
1868
|
+
* Firm only until the quote's `expiresAt`. For a native fee this is the exact
|
|
1869
|
+
* `msg.value`; for an ERC-20 fee this is the amount approved to the wrapper.
|
|
1870
|
+
*/
|
|
1871
|
+
feeTotalAmount: bigint;
|
|
1872
|
+
};
|
|
1873
|
+
}
|
|
1874
|
+
/**
|
|
1875
|
+
* Signed fee quote claim consumed by the `TokenMessengerWithFees` wrapper.
|
|
1876
|
+
*
|
|
1877
|
+
* Mirrors the on-chain `IFeeManager.QuoteClaim` struct.
|
|
1878
|
+
*
|
|
1879
|
+
* @example
|
|
1880
|
+
* ```typescript
|
|
1881
|
+
* const claim: QuoteClaim = {
|
|
1882
|
+
* signedQuote: '0x01...', // [uint8 0x01][abi.encode(Quote)]
|
|
1883
|
+
* refundAddress: '0xUserWallet...',
|
|
1884
|
+
* }
|
|
1885
|
+
* ```
|
|
1886
|
+
*/
|
|
1887
|
+
interface QuoteClaim {
|
|
1888
|
+
/**
|
|
1889
|
+
* Opaque signed quote bytes (`0x` hex) from the fee-quote service
|
|
1890
|
+
* (`SignedFeeQuote.signedQuote` returned by `fetchFeeQuote`). Pass verbatim;
|
|
1891
|
+
* do not decode.
|
|
1892
|
+
*
|
|
1893
|
+
* The quote binds the FORWARD fee item to the on-chain call via `argsHash`;
|
|
1894
|
+
* passing a quote that does not match the burn args reverts `QuoteArgsMismatch`.
|
|
1895
|
+
*/
|
|
1896
|
+
signedQuote: string;
|
|
1897
|
+
/**
|
|
1898
|
+
* Address that receives any refund of overpaid fees.
|
|
1899
|
+
*
|
|
1900
|
+
* Typically the user wallet that authorized the burn.
|
|
1901
|
+
*/
|
|
1902
|
+
refundAddress: string;
|
|
1768
1903
|
}
|
|
1769
1904
|
|
|
1770
1905
|
/**
|
|
@@ -4208,6 +4343,116 @@ interface TokenRegistry {
|
|
|
4208
4343
|
entries(): TokenDefinition[];
|
|
4209
4344
|
}
|
|
4210
4345
|
|
|
4346
|
+
/**
|
|
4347
|
+
* Valid recoverability values for error handling strategies.
|
|
4348
|
+
*
|
|
4349
|
+
* - FATAL errors are thrown immediately (invalid inputs, insufficient funds)
|
|
4350
|
+
* - RETRYABLE errors are returned when a flow fails to start but could work later
|
|
4351
|
+
* - RESUMABLE errors are returned when a flow fails mid-execution but can be continued
|
|
4352
|
+
*/
|
|
4353
|
+
declare const RECOVERABILITY_VALUES: readonly ["RETRYABLE", "RESUMABLE", "FATAL"];
|
|
4354
|
+
/**
|
|
4355
|
+
* Error handling strategy for different types of failures.
|
|
4356
|
+
*
|
|
4357
|
+
* - FATAL errors are thrown immediately (invalid inputs, insufficient funds)
|
|
4358
|
+
* - RETRYABLE errors are returned when a flow fails to start but could work later
|
|
4359
|
+
* - RESUMABLE errors are returned when a flow fails mid-execution but can be continued
|
|
4360
|
+
*/
|
|
4361
|
+
type Recoverability = (typeof RECOVERABILITY_VALUES)[number];
|
|
4362
|
+
/**
|
|
4363
|
+
* Array of valid error type values for validation.
|
|
4364
|
+
* Derived from ERROR_TYPES const object.
|
|
4365
|
+
*/
|
|
4366
|
+
declare const ERROR_TYPE_VALUES: ("INPUT" | "BALANCE" | "ONCHAIN" | "RPC" | "NETWORK" | "RATE_LIMIT" | "SERVICE" | "LIQUIDITY" | "UNKNOWN")[];
|
|
4367
|
+
/**
|
|
4368
|
+
* Error type indicating the category of the error.
|
|
4369
|
+
*/
|
|
4370
|
+
type ErrorType = (typeof ERROR_TYPE_VALUES)[number];
|
|
4371
|
+
/**
|
|
4372
|
+
* Structured error details with consistent properties for programmatic handling.
|
|
4373
|
+
*
|
|
4374
|
+
* This interface provides a standardized format for all errors in the
|
|
4375
|
+
* App Kits system, enabling developers to handle different error
|
|
4376
|
+
* types consistently and provide appropriate user feedback.
|
|
4377
|
+
*
|
|
4378
|
+
* @example
|
|
4379
|
+
* ```typescript
|
|
4380
|
+
* const error: ErrorDetails = {
|
|
4381
|
+
* code: 1001,
|
|
4382
|
+
* name: "INPUT_NETWORK_MISMATCH",
|
|
4383
|
+
* type: "INPUT",
|
|
4384
|
+
* recoverability: "FATAL",
|
|
4385
|
+
* message: "Source and destination networks must be different",
|
|
4386
|
+
* cause: {
|
|
4387
|
+
* trace: { sourceChain: "ethereum", destChain: "ethereum" }
|
|
4388
|
+
* }
|
|
4389
|
+
* }
|
|
4390
|
+
* ```
|
|
4391
|
+
*
|
|
4392
|
+
* @example
|
|
4393
|
+
* ```typescript
|
|
4394
|
+
* const error: ErrorDetails = {
|
|
4395
|
+
* code: 9001,
|
|
4396
|
+
* name: "BALANCE_INSUFFICIENT_TOKEN",
|
|
4397
|
+
* type: "BALANCE",
|
|
4398
|
+
* recoverability: "FATAL",
|
|
4399
|
+
* message: "Insufficient USDC balance on Ethereum",
|
|
4400
|
+
* cause: {
|
|
4401
|
+
* trace: { token: "USDC", chain: "Ethereum" }
|
|
4402
|
+
* }
|
|
4403
|
+
* }
|
|
4404
|
+
* ```
|
|
4405
|
+
*/
|
|
4406
|
+
interface ErrorDetails {
|
|
4407
|
+
/** Numeric identifier following standardized ranges (see error code registry) */
|
|
4408
|
+
code: number;
|
|
4409
|
+
/** Human-readable ID (e.g., "INPUT_NETWORK_MISMATCH", "BALANCE_INSUFFICIENT_TOKEN") */
|
|
4410
|
+
name: string;
|
|
4411
|
+
/** Error category indicating where the error originated */
|
|
4412
|
+
type: ErrorType;
|
|
4413
|
+
/** Error handling strategy */
|
|
4414
|
+
recoverability: Recoverability;
|
|
4415
|
+
/** User-friendly explanation with context */
|
|
4416
|
+
message: string;
|
|
4417
|
+
/** Raw error details, context, or the original error that caused this one. */
|
|
4418
|
+
cause?: {
|
|
4419
|
+
/**
|
|
4420
|
+
* Free-form error payload from the underlying system.
|
|
4421
|
+
*
|
|
4422
|
+
* The shape is **not uniform across error codes**: most codes set `trace`
|
|
4423
|
+
* to the raw underlying error, while a few set a structured wrapper object
|
|
4424
|
+
* `{ rawError, ...extras }` (e.g. `INPUT_AMOUNT_OUT_OF_RANGE` and
|
|
4425
|
+
* `LIQUIDITY_INSUFFICIENT` add `minAmount` / `maxAmount` / `token`).
|
|
4426
|
+
* Consumers must branch on `error.code` before reading structured fields off
|
|
4427
|
+
* `trace`, and should treat the raw error as the fallback for all other codes.
|
|
4428
|
+
*/
|
|
4429
|
+
trace?: unknown;
|
|
4430
|
+
};
|
|
4431
|
+
}
|
|
4432
|
+
|
|
4433
|
+
declare class KitError extends Error implements ErrorDetails {
|
|
4434
|
+
/** Numeric identifier following standardized ranges (1000+ for INPUT errors) */
|
|
4435
|
+
readonly code: number;
|
|
4436
|
+
/** Human-readable ID (e.g., "NETWORK_MISMATCH") */
|
|
4437
|
+
readonly name: string;
|
|
4438
|
+
/** Error category indicating where the error originated */
|
|
4439
|
+
readonly type: ErrorType;
|
|
4440
|
+
/** Error handling strategy */
|
|
4441
|
+
readonly recoverability: Recoverability;
|
|
4442
|
+
/** Raw error details, context, or the original error that caused this one. */
|
|
4443
|
+
readonly cause?: {
|
|
4444
|
+
/** Free-form error payload from underlying system */
|
|
4445
|
+
trace?: unknown;
|
|
4446
|
+
};
|
|
4447
|
+
/**
|
|
4448
|
+
* Create a new KitError instance.
|
|
4449
|
+
*
|
|
4450
|
+
* @param details - The error details object containing all required properties.
|
|
4451
|
+
* @throws \{TypeError\} When details parameter is missing or invalid.
|
|
4452
|
+
*/
|
|
4453
|
+
constructor(details: ErrorDetails);
|
|
4454
|
+
}
|
|
4455
|
+
|
|
4211
4456
|
/**
|
|
4212
4457
|
* Structured fields that can be attached to log entries.
|
|
4213
4458
|
*/
|
|
@@ -6194,101 +6439,530 @@ interface ICCTPV2BridgingProvider extends BridgingProvider<CCTPV2Actions> {
|
|
|
6194
6439
|
}
|
|
6195
6440
|
|
|
6196
6441
|
/**
|
|
6197
|
-
*
|
|
6442
|
+
* Get the token account address where USDC will be minted for the recipient.
|
|
6198
6443
|
*
|
|
6199
|
-
*
|
|
6200
|
-
*
|
|
6201
|
-
*
|
|
6202
|
-
*
|
|
6444
|
+
* For EVM chains, the recipient address directly holds ERC20 tokens, so the raw
|
|
6445
|
+
* address is returned as-is. For Solana, USDC is held in Associated Token Accounts
|
|
6446
|
+
* (ATAs), so this function derives the ATA address for the given owner and USDC mint.
|
|
6447
|
+
*
|
|
6448
|
+
* @param chainType - The type of blockchain ('evm' or 'solana').
|
|
6449
|
+
* @param rawAddress - The recipient's wallet address on the destination chain.
|
|
6450
|
+
* @param mint - The USDC mint address (only used for Solana chains).
|
|
6451
|
+
* @returns The address where USDC tokens will be minted (raw address for EVM, ATA for Solana).
|
|
6452
|
+
*
|
|
6453
|
+
* @example
|
|
6454
|
+
* ```typescript
|
|
6455
|
+
* import { getMintRecipientAccount } from './getMintRecipientAccount'
|
|
6456
|
+
*
|
|
6457
|
+
* // EVM: returns the same address
|
|
6458
|
+
* const evmAccount = await getMintRecipientAccount(
|
|
6459
|
+
* 'evm',
|
|
6460
|
+
* '0x742d35Cc6634C0532925a3b8D89C7DA5C3cfa',
|
|
6461
|
+
* 'N/A'
|
|
6462
|
+
* )
|
|
6463
|
+
*
|
|
6464
|
+
* // Solana: derives the Associated Token Account
|
|
6465
|
+
* const solanaAccount = await getMintRecipientAccount(
|
|
6466
|
+
* 'solana',
|
|
6467
|
+
* '9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM',
|
|
6468
|
+
* 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
|
|
6469
|
+
* )
|
|
6470
|
+
* ```
|
|
6203
6471
|
*/
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
* @remarks
|
|
6213
|
-
* Headers are merged on top of the defaults (such as `Content-Type`) without
|
|
6214
|
-
* removing them. The header is forwarded as-is to Circle's API; the SDK does
|
|
6215
|
-
* not interpret it.
|
|
6216
|
-
*
|
|
6217
|
-
* Precedence (lowest to highest): provider defaults, then these
|
|
6218
|
-
* `config.headers`, then any per-call `config.headers` passed to
|
|
6219
|
-
* {@link CCTPV2BridgingProvider.fetchAttestation},
|
|
6220
|
-
* {@link CCTPV2BridgingProvider.fetchRelayerMint}, or
|
|
6221
|
-
* {@link CCTPV2BridgingProvider.reAttest}.
|
|
6222
|
-
*/
|
|
6223
|
-
headers?: Record<string, string>;
|
|
6224
|
-
}
|
|
6472
|
+
declare const getMintRecipientAccount: (
|
|
6473
|
+
/** The blockchain type - determines how token accounts are handled */
|
|
6474
|
+
chainType: ChainType,
|
|
6475
|
+
/** The recipient's wallet address (hex format for EVM, base58 for Solana) */
|
|
6476
|
+
rawAddress: string,
|
|
6477
|
+
/** The USDC mint address (ignored for EVM chains, required base58 address for Solana) */
|
|
6478
|
+
mintAddress: string) => Promise<string>;
|
|
6479
|
+
|
|
6225
6480
|
/**
|
|
6226
|
-
*
|
|
6481
|
+
* Validates and converts a fee value to bigint.
|
|
6227
6482
|
*
|
|
6228
|
-
* This
|
|
6229
|
-
*
|
|
6230
|
-
*
|
|
6483
|
+
* This utility performs:
|
|
6484
|
+
* 1. Conversion from string or number to bigint
|
|
6485
|
+
* 2. Validation that the value is non-negative
|
|
6231
6486
|
*
|
|
6232
|
-
*
|
|
6233
|
-
*
|
|
6234
|
-
*
|
|
6235
|
-
*
|
|
6236
|
-
* - **Observable**: Rich event emission for monitoring and debugging
|
|
6487
|
+
* @param value - The fee value to validate and convert (string or number)
|
|
6488
|
+
* @param fieldName - The name of the field for error messages
|
|
6489
|
+
* @returns The validated fee as a bigint
|
|
6490
|
+
* @throws {KitError} If the value cannot be converted to bigint or is negative
|
|
6237
6491
|
*
|
|
6238
6492
|
* @example
|
|
6239
6493
|
* ```typescript
|
|
6240
|
-
*
|
|
6241
|
-
*
|
|
6494
|
+
* const fee = validateAndConvertFee('1000000', 'minimumFee')
|
|
6495
|
+
* console.log(fee) // 1000000n
|
|
6242
6496
|
*
|
|
6243
|
-
* const
|
|
6497
|
+
* const fee2 = validateAndConvertFee(500, 'forwardingFee')
|
|
6498
|
+
* console.log(fee2) // 500n
|
|
6499
|
+
* ```
|
|
6500
|
+
*/
|
|
6501
|
+
declare function validateAndConvertFee(value: number | string, fieldName: string): bigint;
|
|
6502
|
+
|
|
6503
|
+
/** A block number value that can be provided as bigint, number, or string. */
|
|
6504
|
+
type BlockNumberInput = bigint | number | string | undefined;
|
|
6505
|
+
/**
|
|
6506
|
+
* Determines whether an attestation has expired based on the current block number.
|
|
6244
6507
|
*
|
|
6245
|
-
*
|
|
6246
|
-
*
|
|
6508
|
+
* An attestation expires when the destination chain's current block number is greater
|
|
6509
|
+
* than or equal to the expiration block specified in the attestation message.
|
|
6510
|
+
* Slow transfers and re-attested messages have `expirationBlock: '0'` and never expire.
|
|
6247
6511
|
*
|
|
6248
|
-
*
|
|
6249
|
-
*
|
|
6250
|
-
*
|
|
6512
|
+
* @param attestation - The attestation message containing expiration block information
|
|
6513
|
+
* @param currentBlockNumber - The current block number on the destination chain (bigint, number, or string)
|
|
6514
|
+
* @returns `true` if the attestation has expired, `false` if still valid or never expires
|
|
6515
|
+
* @throws KitError If currentBlockNumber or expirationBlock is invalid
|
|
6251
6516
|
*
|
|
6252
|
-
*
|
|
6253
|
-
*
|
|
6254
|
-
*
|
|
6255
|
-
* destination: { adapter: destAdapter, chain: 'Base' },
|
|
6256
|
-
* amount: '10.50',
|
|
6257
|
-
* token: 'USDC',
|
|
6258
|
-
* config: {
|
|
6259
|
-
* transferSpeed: 'FAST',
|
|
6260
|
-
* },
|
|
6261
|
-
* }
|
|
6517
|
+
* @example
|
|
6518
|
+
* ```typescript
|
|
6519
|
+
* import { isAttestationExpired } from '@circle-fin/cctp-v2-provider'
|
|
6262
6520
|
*
|
|
6263
|
-
* //
|
|
6264
|
-
* const
|
|
6265
|
-
*
|
|
6521
|
+
* // Check if attestation is expired on EVM chain
|
|
6522
|
+
* const publicClient = await adapter.getPublicClient(destinationChain)
|
|
6523
|
+
* const currentBlock = await publicClient.getBlockNumber()
|
|
6524
|
+
* const expired = isAttestationExpired(attestation, currentBlock)
|
|
6266
6525
|
*
|
|
6267
|
-
*
|
|
6268
|
-
*
|
|
6269
|
-
*
|
|
6526
|
+
* if (expired) {
|
|
6527
|
+
* const freshAttestation = await provider.reAttest(source, burnTxHash)
|
|
6528
|
+
* }
|
|
6529
|
+
* ```
|
|
6530
|
+
*
|
|
6531
|
+
* @example
|
|
6532
|
+
* ```typescript
|
|
6533
|
+
* // Check on Solana
|
|
6534
|
+
* const slot = await adapter.getConnection(destinationChain).getSlot()
|
|
6535
|
+
* const expired = isAttestationExpired(attestation, slot)
|
|
6270
6536
|
* ```
|
|
6271
6537
|
*/
|
|
6272
|
-
declare
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6290
|
-
|
|
6291
|
-
|
|
6538
|
+
declare const isAttestationExpired: (attestation: AttestationMessage, currentBlockNumber: BlockNumberInput) => boolean;
|
|
6539
|
+
/**
|
|
6540
|
+
* Calculates the number of blocks remaining until an attestation expires.
|
|
6541
|
+
*
|
|
6542
|
+
* Returns the difference between the expiration block and the current block number.
|
|
6543
|
+
* Returns `null` if the attestation has `expirationBlock: '0'` (never expires).
|
|
6544
|
+
* Returns `0n` or a negative bigint if the attestation has already expired.
|
|
6545
|
+
*
|
|
6546
|
+
* @param attestation - The attestation message containing expiration block information
|
|
6547
|
+
* @param currentBlockNumber - The current block number on the destination chain (bigint, number, or string)
|
|
6548
|
+
* @returns The number of blocks until expiry as a bigint, or `null` if the attestation never expires
|
|
6549
|
+
* @throws KitError If currentBlockNumber or expirationBlock is invalid
|
|
6550
|
+
*
|
|
6551
|
+
* @example
|
|
6552
|
+
* ```typescript
|
|
6553
|
+
* import { getBlocksUntilExpiry } from '@circle-fin/cctp-v2-provider'
|
|
6554
|
+
*
|
|
6555
|
+
* const publicClient = await adapter.getPublicClient(destinationChain)
|
|
6556
|
+
* const currentBlock = await publicClient.getBlockNumber()
|
|
6557
|
+
* const blocksRemaining = getBlocksUntilExpiry(attestation, currentBlock)
|
|
6558
|
+
*
|
|
6559
|
+
* if (blocksRemaining === null) {
|
|
6560
|
+
* console.log('Attestation never expires')
|
|
6561
|
+
* } else if (blocksRemaining <= 0n) {
|
|
6562
|
+
* console.log('Attestation has expired')
|
|
6563
|
+
* } else {
|
|
6564
|
+
* console.log(`${blocksRemaining} blocks until expiry`)
|
|
6565
|
+
* }
|
|
6566
|
+
* ```
|
|
6567
|
+
*/
|
|
6568
|
+
declare const getBlocksUntilExpiry: (attestation: AttestationMessage, currentBlockNumber: BlockNumberInput) => bigint | null;
|
|
6569
|
+
/**
|
|
6570
|
+
* Determines whether a mint failure was caused by an expired attestation.
|
|
6571
|
+
*
|
|
6572
|
+
* This function inspects the error thrown during a mint operation to detect
|
|
6573
|
+
* if the failure is due to the attestation's expiration block being exceeded.
|
|
6574
|
+
* When this returns `true`, the caller should use `reAttest()` to obtain a
|
|
6575
|
+
* fresh attestation before retrying the mint.
|
|
6576
|
+
*
|
|
6577
|
+
* @param error - The error thrown during the mint operation
|
|
6578
|
+
* @returns `true` if the error indicates the attestation has expired, `false` otherwise
|
|
6579
|
+
*
|
|
6580
|
+
* @example
|
|
6581
|
+
* ```typescript
|
|
6582
|
+
* import { isMintFailureRelatedToAttestation } from '@circle-fin/cctp-v2-provider'
|
|
6583
|
+
*
|
|
6584
|
+
* try {
|
|
6585
|
+
* await mintRequest.execute()
|
|
6586
|
+
* } catch (error) {
|
|
6587
|
+
* if (isMintFailureRelatedToAttestation(error)) {
|
|
6588
|
+
* // Attestation expired - get a fresh one
|
|
6589
|
+
* const freshAttestation = await provider.reAttest(source, burnTxHash)
|
|
6590
|
+
* const newMintRequest = await provider.mint(source, destination, freshAttestation)
|
|
6591
|
+
* await newMintRequest.execute()
|
|
6592
|
+
* } else {
|
|
6593
|
+
* throw error
|
|
6594
|
+
* }
|
|
6595
|
+
* }
|
|
6596
|
+
* ```
|
|
6597
|
+
*/
|
|
6598
|
+
declare const isMintFailureRelatedToAttestation: (error: unknown) => boolean;
|
|
6599
|
+
|
|
6600
|
+
/**
|
|
6601
|
+
* An ERC-20 approval required before a prepaid-FORWARD burn.
|
|
6602
|
+
*
|
|
6603
|
+
* @example
|
|
6604
|
+
* ```typescript
|
|
6605
|
+
* const approval: FeeApproval = {
|
|
6606
|
+
* token: '0xUSDC...',
|
|
6607
|
+
* amount: 1_003_500_000n,
|
|
6608
|
+
* }
|
|
6609
|
+
* ```
|
|
6610
|
+
*/
|
|
6611
|
+
interface FeeApproval {
|
|
6612
|
+
/**
|
|
6613
|
+
* Token address to approve (the burn token and/or the ERC-20 fee token).
|
|
6614
|
+
*/
|
|
6615
|
+
token: string;
|
|
6616
|
+
/**
|
|
6617
|
+
* Amount to approve to the `TokenMessengerWithFees` wrapper, in token minor units.
|
|
6618
|
+
*/
|
|
6619
|
+
amount: bigint;
|
|
6620
|
+
}
|
|
6621
|
+
/**
|
|
6622
|
+
* The resolved fee payment channel for a prepaid-FORWARD burn.
|
|
6623
|
+
*
|
|
6624
|
+
* @example
|
|
6625
|
+
* ```typescript
|
|
6626
|
+
* const plan: FeePaymentPlan = {
|
|
6627
|
+
* isNativeFee: false,
|
|
6628
|
+
* isBurnTokenFee: true,
|
|
6629
|
+
* nativeValue: 0n,
|
|
6630
|
+
* approvals: [{ token: '0xUSDC...', amount: 1_003_500_000n }],
|
|
6631
|
+
* }
|
|
6632
|
+
* ```
|
|
6633
|
+
*/
|
|
6634
|
+
interface FeePaymentPlan {
|
|
6635
|
+
/**
|
|
6636
|
+
* True when the fee is paid in native currency (`feeToken` is the zero address).
|
|
6637
|
+
*/
|
|
6638
|
+
isNativeFee: boolean;
|
|
6639
|
+
/**
|
|
6640
|
+
* True when the fee token is the same token being burned (both USDC).
|
|
6641
|
+
*
|
|
6642
|
+
* In this case a single, combined approval covers both the burn and the fee,
|
|
6643
|
+
* so the redundant second approval is skipped.
|
|
6644
|
+
*/
|
|
6645
|
+
isBurnTokenFee: boolean;
|
|
6646
|
+
/**
|
|
6647
|
+
* Native value to attach as `msg.value`.
|
|
6648
|
+
*
|
|
6649
|
+
* Exactly `feeTotalAmount` for a native fee; `0n` for an ERC-20 fee.
|
|
6650
|
+
*/
|
|
6651
|
+
nativeValue: bigint;
|
|
6652
|
+
/**
|
|
6653
|
+
* ERC-20 approvals required before the burn, each to the `TokenMessengerWithFees`
|
|
6654
|
+
* wrapper.
|
|
6655
|
+
*
|
|
6656
|
+
* - Native fee: a single approval of `amount` for the burn token.
|
|
6657
|
+
* - ERC-20 fee equal to the burn token: a single approval of `amount + feeTotalAmount`.
|
|
6658
|
+
* - ERC-20 fee different from the burn token: two approvals — `amount` for the
|
|
6659
|
+
* burn token and `feeTotalAmount` for the fee token.
|
|
6660
|
+
*/
|
|
6661
|
+
approvals: FeeApproval[];
|
|
6662
|
+
}
|
|
6663
|
+
/**
|
|
6664
|
+
* Parameters for {@link resolveFeePayment}.
|
|
6665
|
+
*/
|
|
6666
|
+
interface ResolveFeePaymentParams {
|
|
6667
|
+
/**
|
|
6668
|
+
* Fee token from the signed quote. The zero address denotes a native fee.
|
|
6669
|
+
*/
|
|
6670
|
+
feeToken: string;
|
|
6671
|
+
/**
|
|
6672
|
+
* The token being burned (always USDC on the burn path).
|
|
6673
|
+
*/
|
|
6674
|
+
burnToken: string;
|
|
6675
|
+
/**
|
|
6676
|
+
* Amount of the burn token to burn, in minor units.
|
|
6677
|
+
*/
|
|
6678
|
+
amount: bigint;
|
|
6679
|
+
/**
|
|
6680
|
+
* Total fee amount from the signed quote, in `feeToken` minor units.
|
|
6681
|
+
*/
|
|
6682
|
+
feeTotalAmount: bigint;
|
|
6683
|
+
}
|
|
6684
|
+
/**
|
|
6685
|
+
* Resolve the fee payment channel for a prepaid-FORWARD burn via `TokenMessengerWithFees`.
|
|
6686
|
+
*
|
|
6687
|
+
* Determines the native `msg.value` and the ERC-20 approvals required, honouring
|
|
6688
|
+
* the quote's `feeToken`:
|
|
6689
|
+
* - Native fee (`feeToken` is the zero address): attach exactly `feeTotalAmount`
|
|
6690
|
+
* as `msg.value`; approve only the burn amount.
|
|
6691
|
+
* - ERC-20 fee equal to the burn token (both USDC — the `isBurnTokenFee` case):
|
|
6692
|
+
* approve a single combined `amount + feeTotalAmount` and skip the redundant
|
|
6693
|
+
* second approval.
|
|
6694
|
+
* - ERC-20 fee different from the burn token: approve the burn amount and the fee
|
|
6695
|
+
* amount separately.
|
|
6696
|
+
*
|
|
6697
|
+
* This encodes only balance/allowance intent; it does not fetch balances. The
|
|
6698
|
+
* caller is responsible for a balance preflight against the fresh quote.
|
|
6699
|
+
*
|
|
6700
|
+
* @param params - The fee token, burn token, burn amount, and total fee amount.
|
|
6701
|
+
* @returns The resolved fee payment plan.
|
|
6702
|
+
* @throws KitError if `amount` or `feeTotalAmount` is negative.
|
|
6703
|
+
*
|
|
6704
|
+
* @example
|
|
6705
|
+
* ```typescript
|
|
6706
|
+
* // Native fee
|
|
6707
|
+
* resolveFeePayment({
|
|
6708
|
+
* feeToken: '0x0000000000000000000000000000000000000000',
|
|
6709
|
+
* burnToken: '0xUSDC...',
|
|
6710
|
+
* amount: 1_000_000n,
|
|
6711
|
+
* feeTotalAmount: 3_500_000n,
|
|
6712
|
+
* })
|
|
6713
|
+
* // → { isNativeFee: true, isBurnTokenFee: false, nativeValue: 3_500_000n,
|
|
6714
|
+
* // approvals: [{ token: '0xUSDC...', amount: 1_000_000n }] }
|
|
6715
|
+
* ```
|
|
6716
|
+
*/
|
|
6717
|
+
declare const resolveFeePayment: (params: ResolveFeePaymentParams) => FeePaymentPlan;
|
|
6718
|
+
|
|
6719
|
+
/**
|
|
6720
|
+
* Custom errors reverted by the `TokenMessengerWithFees` wrapper on the prepaid
|
|
6721
|
+
* FORWARD path.
|
|
6722
|
+
*
|
|
6723
|
+
* - `IncorrectNativePayment` — `msg.value` did not equal the quoted native fee.
|
|
6724
|
+
* - `ForwardFeeWithoutHook` — the quote has a FORWARD item but the hookData lacks
|
|
6725
|
+
* a `cctp-forward` frame.
|
|
6726
|
+
* - `ForwardHookWithoutFee` — the hookData has a `cctp-forward` frame but the quote
|
|
6727
|
+
* omits a FORWARD item.
|
|
6728
|
+
* - `QuoteArgsMismatch` — the signed quote's `argsHash` does not match the on-chain
|
|
6729
|
+
* call arguments (wrong hookData/destinationCaller/amount/etc.).
|
|
6730
|
+
* - `InvalidQuoteSigner` — the signed quote was not signed by a recognized signer.
|
|
6731
|
+
*/
|
|
6732
|
+
declare const PREPAID_FORWARD_REVERT_NAMES: readonly ["IncorrectNativePayment", "ForwardFeeWithoutHook", "ForwardHookWithoutFee", "QuoteArgsMismatch", "InvalidQuoteSigner"];
|
|
6733
|
+
/**
|
|
6734
|
+
* A `TokenMessengerWithFees` custom revert name.
|
|
6735
|
+
*/
|
|
6736
|
+
type PrepaidForwardRevertName = (typeof PREPAID_FORWARD_REVERT_NAMES)[number];
|
|
6737
|
+
/**
|
|
6738
|
+
* Determine whether a hookData blob begins with the `cctp-forward` envelope.
|
|
6739
|
+
*
|
|
6740
|
+
* The prepaid FORWARD path requires the GenericExecutor blob to be wrapped in a
|
|
6741
|
+
* `cctp-forward` frame; without it the wrapper reverts `ForwardFeeWithoutHook`.
|
|
6742
|
+
*
|
|
6743
|
+
* @param hookData - The 0x-prefixed hookData hex string.
|
|
6744
|
+
* @returns True when the hookData starts with the `cctp-forward` magic.
|
|
6745
|
+
*
|
|
6746
|
+
* @example
|
|
6747
|
+
* ```typescript
|
|
6748
|
+
* hasForwardHook('0x636374702d666f7277617264...') // true
|
|
6749
|
+
* hasForwardHook('0xdeadbeef') // false
|
|
6750
|
+
* ```
|
|
6751
|
+
*/
|
|
6752
|
+
declare const hasForwardHook: (hookData: string | undefined) => boolean;
|
|
6753
|
+
/**
|
|
6754
|
+
* Assert that a hookData blob is forward-friendly for the prepaid FORWARD path.
|
|
6755
|
+
*
|
|
6756
|
+
* The prepaid FORWARD path always requests a FORWARD fee item, so the wrapper
|
|
6757
|
+
* requires the hookData to start with a `cctp-forward` frame. Validating this
|
|
6758
|
+
* before the burn surfaces the guaranteed `ForwardFeeWithoutHook` revert as a
|
|
6759
|
+
* typed input error instead of an on-chain failure.
|
|
6760
|
+
*
|
|
6761
|
+
* @param hookData - The 0x-prefixed hookData hex string.
|
|
6762
|
+
* @throws KitError (`INPUT_VALIDATION_FAILED`) if the hookData is missing or lacks
|
|
6763
|
+
* the `cctp-forward` frame.
|
|
6764
|
+
*
|
|
6765
|
+
* @example
|
|
6766
|
+
* ```typescript
|
|
6767
|
+
* assertForwardHookData(geForwardHookData) // ok
|
|
6768
|
+
* assertForwardHookData('0xdeadbeef') // throws — would revert ForwardFeeWithoutHook
|
|
6769
|
+
* ```
|
|
6770
|
+
*/
|
|
6771
|
+
declare const assertForwardHookData: (hookData: string | undefined) => void;
|
|
6772
|
+
/**
|
|
6773
|
+
* Map a raw error thrown while submitting a prepaid-FORWARD burn to a typed error.
|
|
6774
|
+
*
|
|
6775
|
+
* Inspects the error for a known `TokenMessengerWithFees` custom revert name and,
|
|
6776
|
+
* when found, returns a structured {@link KitError} describing it. Returns
|
|
6777
|
+
* `undefined` when the error is not a recognized wrapper revert so the caller can
|
|
6778
|
+
* fall through to generic blockchain-error parsing.
|
|
6779
|
+
*
|
|
6780
|
+
* @param error - The error thrown by transaction simulation or execution.
|
|
6781
|
+
* @param chain - The source chain name, for the error message.
|
|
6782
|
+
* @returns A typed {@link KitError} for a recognized wrapper revert, else `undefined`.
|
|
6783
|
+
*
|
|
6784
|
+
* @example
|
|
6785
|
+
* ```typescript
|
|
6786
|
+
* try {
|
|
6787
|
+
* await prepared.execute()
|
|
6788
|
+
* } catch (error) {
|
|
6789
|
+
* throw mapPrepaidForwardError(error, 'Ethereum') ?? parseBlockchainError(error, { chain: 'Ethereum' })
|
|
6790
|
+
* }
|
|
6791
|
+
* ```
|
|
6792
|
+
*/
|
|
6793
|
+
declare const mapPrepaidForwardError: (error: unknown, chain: string) => KitError | undefined;
|
|
6794
|
+
|
|
6795
|
+
/**
|
|
6796
|
+
* Configuration options for the CCTP v2 provider.
|
|
6797
|
+
*
|
|
6798
|
+
* @remarks
|
|
6799
|
+
* This interface defines all configurable aspects of the CCTP v2 provider:
|
|
6800
|
+
* - attestation: Settings for the attestation fetching process
|
|
6801
|
+
* - headers: Custom HTTP headers sent with every Circle attestation API request
|
|
6802
|
+
*/
|
|
6803
|
+
interface CCTPV2Config {
|
|
6804
|
+
/** Configuration for the attestation fetching process */
|
|
6805
|
+
attestation?: Partial<ApiPollingConfig>;
|
|
6806
|
+
/**
|
|
6807
|
+
* Custom HTTP headers sent with every Circle attestation (Iris) API request
|
|
6808
|
+
* made by the provider (attestation fetch, re-attestation, and relayer mint
|
|
6809
|
+
* status polling).
|
|
6810
|
+
*
|
|
6811
|
+
* @remarks
|
|
6812
|
+
* Headers are merged on top of the defaults (such as `Content-Type`) without
|
|
6813
|
+
* removing them. The header is forwarded as-is to Circle's API; the SDK does
|
|
6814
|
+
* not interpret it.
|
|
6815
|
+
*
|
|
6816
|
+
* Precedence (lowest to highest): provider defaults, then these
|
|
6817
|
+
* `config.headers`, then any per-call `config.headers` passed to
|
|
6818
|
+
* {@link CCTPV2BridgingProvider.fetchAttestation},
|
|
6819
|
+
* {@link CCTPV2BridgingProvider.fetchRelayerMint}, or
|
|
6820
|
+
* {@link CCTPV2BridgingProvider.reAttest}.
|
|
6821
|
+
*/
|
|
6822
|
+
headers?: Record<string, string>;
|
|
6823
|
+
}
|
|
6824
|
+
/**
|
|
6825
|
+
* Parameters for a prepaid-FORWARD burn via {@link CCTPV2BridgingProvider.burnWithFees}.
|
|
6826
|
+
*
|
|
6827
|
+
* @typeParam TFromAdapterCapabilities - The source adapter's capabilities.
|
|
6828
|
+
*/
|
|
6829
|
+
interface BurnWithFeesParams<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities> {
|
|
6830
|
+
/**
|
|
6831
|
+
* Source wallet context (adapter + CCTP v2 source chain).
|
|
6832
|
+
*/
|
|
6833
|
+
source: WalletContext<TFromAdapterCapabilities, ChainDefinitionWithCCTPv2>;
|
|
6834
|
+
/**
|
|
6835
|
+
* Destination chain definition (provides the destination CCTP domain).
|
|
6836
|
+
*/
|
|
6837
|
+
destinationChain: ChainDefinitionWithCCTPv2;
|
|
6838
|
+
/**
|
|
6839
|
+
* Amount of USDC to burn, in minor units.
|
|
6840
|
+
*/
|
|
6841
|
+
amount: string | bigint;
|
|
6842
|
+
/**
|
|
6843
|
+
* The GenericExecutor address on the destination chain.
|
|
6844
|
+
*
|
|
6845
|
+
* Used for BOTH `mintRecipient` and `destinationCaller` (padded to bytes32 by
|
|
6846
|
+
* the underlying action): the executor mints to itself and is the only account
|
|
6847
|
+
* allowed to complete the transfer.
|
|
6848
|
+
*/
|
|
6849
|
+
executor: string;
|
|
6850
|
+
/**
|
|
6851
|
+
* The `cctp-forward`-wrapped GenericExecutor hookData blob.
|
|
6852
|
+
*
|
|
6853
|
+
* Produced with `@core/utils`: wrap the bare blob from
|
|
6854
|
+
* `buildDepositForGenericExecutorPayload(...).hookData` with
|
|
6855
|
+
* `buildForwardingHookDataWithPayload(version, bareBlob)`. It must begin with
|
|
6856
|
+
* the `cctp-forward` frame, or the wrapper reverts `ForwardFeeWithoutHook`.
|
|
6857
|
+
*
|
|
6858
|
+
* Pass the SAME wrapped bytes here that were bound to the FORWARD fee quote
|
|
6859
|
+
* (`fetchFeeQuote` FORWARD `params.hookData`); mismatched bytes revert
|
|
6860
|
+
* `QuoteArgsMismatch`. Do not pass the bare (`circle-generic-executor`) blob.
|
|
6861
|
+
*/
|
|
6862
|
+
hookData: string;
|
|
6863
|
+
/**
|
|
6864
|
+
* Signed fee quote claim (`{ signedQuote, refundAddress }`).
|
|
6865
|
+
*/
|
|
6866
|
+
claim: QuoteClaim;
|
|
6867
|
+
/**
|
|
6868
|
+
* Fee token from the quote. The zero address denotes a native fee.
|
|
6869
|
+
*/
|
|
6870
|
+
feeToken: string;
|
|
6871
|
+
/**
|
|
6872
|
+
* Total fee amount from the quote, in `feeToken` minor units.
|
|
6873
|
+
*/
|
|
6874
|
+
feeTotalAmount: string | bigint;
|
|
6875
|
+
}
|
|
6876
|
+
/**
|
|
6877
|
+
* Result of {@link CCTPV2BridgingProvider.burnWithFees}.
|
|
6878
|
+
*
|
|
6879
|
+
* The prepared requests are returned unexecuted; the caller executes the
|
|
6880
|
+
* approvals first (in order) and then the burn.
|
|
6881
|
+
*/
|
|
6882
|
+
interface BurnWithFeesResult {
|
|
6883
|
+
/**
|
|
6884
|
+
* ERC-20 approvals to the `TokenMessengerWithFees` wrapper required before the
|
|
6885
|
+
* burn. Always contains at least one entry: the burn-token approval. A
|
|
6886
|
+
* distinct fee-token approval is added only when the fee token differs from
|
|
6887
|
+
* the burn token and is not the native token.
|
|
6888
|
+
*/
|
|
6889
|
+
approvals: PreparedChainRequest[];
|
|
6890
|
+
/**
|
|
6891
|
+
* The prepared `depositForBurnWithHookAndFees` burn transaction.
|
|
6892
|
+
*/
|
|
6893
|
+
burn: PreparedChainRequest;
|
|
6894
|
+
/**
|
|
6895
|
+
* The resolved fee payment plan (native value, approvals, and flags).
|
|
6896
|
+
*/
|
|
6897
|
+
feePayment: FeePaymentPlan;
|
|
6898
|
+
}
|
|
6899
|
+
/**
|
|
6900
|
+
* Concrete implementation of BridgingProvider for Circle's Cross-Chain Transfer Protocol (CCTP) version 2.
|
|
6901
|
+
*
|
|
6902
|
+
* This provider handles cross-chain bridging using CCTP v2 contracts, which enable native USDC
|
|
6903
|
+
* bridging between supported blockchain networks. The provider supports burn-and-mint operations
|
|
6904
|
+
* with built-in validation, fee estimation, and transaction monitoring.
|
|
6905
|
+
*
|
|
6906
|
+
* The CCTPv2 provider is designed to be:
|
|
6907
|
+
* - **Type-safe**: Full TypeScript support with comprehensive validation
|
|
6908
|
+
* - **Flexible**: Support for both FAST and SLOW bridge configurations
|
|
6909
|
+
* - **Reliable**: Built-in error handling and recovery mechanisms
|
|
6910
|
+
* - **Observable**: Rich event emission for monitoring and debugging
|
|
6911
|
+
*
|
|
6912
|
+
* @example
|
|
6913
|
+
* ```typescript
|
|
6914
|
+
* import { CCTPV2BridgingProvider } from '@circle-fin/provider-cctp-v2'
|
|
6915
|
+
* import { createEvmAdapter } from '@circle-fin/adapter-viem-v2'
|
|
6916
|
+
*
|
|
6917
|
+
* const provider = new CCTPV2BridgingProvider()
|
|
6918
|
+
*
|
|
6919
|
+
* // Check route support
|
|
6920
|
+
* const isSupported = provider.supportsRoute('Ethereum', 'Base', 'USDC')
|
|
6921
|
+
*
|
|
6922
|
+
* // Create adapters
|
|
6923
|
+
* const sourceAdapter = createEvmAdapter({ privateKey: '0x...' })
|
|
6924
|
+
* const destAdapter = createEvmAdapter({ privateKey: '0x...' })
|
|
6925
|
+
*
|
|
6926
|
+
* // Prepare bridge parameters
|
|
6927
|
+
* const params: BridgeParams = {
|
|
6928
|
+
* source: { adapter: sourceAdapter, chain: 'Ethereum' },
|
|
6929
|
+
* destination: { adapter: destAdapter, chain: 'Base' },
|
|
6930
|
+
* amount: '10.50',
|
|
6931
|
+
* token: 'USDC',
|
|
6932
|
+
* config: {
|
|
6933
|
+
* transferSpeed: 'FAST',
|
|
6934
|
+
* },
|
|
6935
|
+
* }
|
|
6936
|
+
*
|
|
6937
|
+
* // Estimate bridge costs
|
|
6938
|
+
* const estimate = await provider.estimate(params)
|
|
6939
|
+
* console.log('Estimated cost:', estimate.totalCost)
|
|
6940
|
+
*
|
|
6941
|
+
* // Execute bridge operation (when implemented)
|
|
6942
|
+
* const result = await provider.bridge(params)
|
|
6943
|
+
* console.log('Bridge completed!')
|
|
6944
|
+
* ```
|
|
6945
|
+
*/
|
|
6946
|
+
declare class CCTPV2BridgingProvider extends BridgingProvider<CCTPV2Actions> implements ICCTPV2BridgingProvider {
|
|
6947
|
+
/** The name of the provider */
|
|
6948
|
+
readonly name = "CCTPV2BridgingProvider";
|
|
6949
|
+
/**
|
|
6950
|
+
* The chains that this provider supports.
|
|
6951
|
+
*/
|
|
6952
|
+
supportedChains: ChainDefinition[];
|
|
6953
|
+
/**
|
|
6954
|
+
* The provider's configuration.
|
|
6955
|
+
*/
|
|
6956
|
+
private readonly config;
|
|
6957
|
+
/**
|
|
6958
|
+
* Creates a new instance of the CCTP v2 bridging provider.
|
|
6959
|
+
*
|
|
6960
|
+
* @param config - Optional configuration overrides for the provider
|
|
6961
|
+
*/
|
|
6962
|
+
constructor(config?: CCTPV2Config);
|
|
6963
|
+
/**
|
|
6964
|
+
* Resolves the effective polling configuration for an attestation request.
|
|
6965
|
+
*
|
|
6292
6966
|
* Precedence (lowest to highest): provider `config.attestation`, then the
|
|
6293
6967
|
* per-call `config`. Headers merge independently across
|
|
6294
6968
|
* `config.attestation.headers`, the provider-level `config.headers`, and any
|
|
@@ -6730,6 +7404,57 @@ declare class CCTPV2BridgingProvider extends BridgingProvider<CCTPV2Actions> imp
|
|
|
6730
7404
|
* ```
|
|
6731
7405
|
*/
|
|
6732
7406
|
burn<TFromAdapterCapabilities extends AdapterCapabilities, TToAdapterCapabilities extends AdapterCapabilities>(params: BridgeParams<TFromAdapterCapabilities, TToAdapterCapabilities>): Promise<PreparedChainRequest>;
|
|
7407
|
+
/**
|
|
7408
|
+
* Prepare a prepaid-FORWARD burn through the `TokenMessengerWithFees` wrapper.
|
|
7409
|
+
*
|
|
7410
|
+
* Builds the source-chain `depositForBurnWithHookAndFees` call for the
|
|
7411
|
+
* GenericExecutor FORWARD path: fees are collected up front on the source chain
|
|
7412
|
+
* against a signed quote, `mintRecipient` and `destinationCaller` are both set to
|
|
7413
|
+
* the GenericExecutor, and the GE `hookData` is passed through unchanged.
|
|
7414
|
+
*
|
|
7415
|
+
* This is the low-level on-chain primitive behind the UBK `fastCrossChainDeposit`
|
|
7416
|
+
* and Bridge Kit `bridge({ deposit })` flows. The `hookData` and signed-quote
|
|
7417
|
+
* `claim` are produced elsewhere and passed in here:
|
|
7418
|
+
* - `hookData`: `buildForwardingHookDataWithPayload(version,
|
|
7419
|
+
* buildDepositForGenericExecutorPayload(...).hookData)` from `@core/utils`.
|
|
7420
|
+
* - `claim.signedQuote` / `feeToken` / `feeTotalAmount`: from `fetchFeeQuote`
|
|
7421
|
+
* (`@circle-fin/provider-fee-v1`), whose FORWARD item must be bound to the
|
|
7422
|
+
* SAME `hookData` and executor `destinationCaller` used here.
|
|
7423
|
+
*
|
|
7424
|
+
* The returned approvals and burn are NOT executed — the caller executes the
|
|
7425
|
+
* approvals first (in order) and then the burn. The fee payment channel matches
|
|
7426
|
+
* the quote's `feeToken`:
|
|
7427
|
+
* - Native fee: exactly `feeTotalAmount` is attached as the burn's `msg.value`;
|
|
7428
|
+
* only the burn amount is approved.
|
|
7429
|
+
* - USDC fee (same token as the burn): a single combined `amount + feeTotalAmount`
|
|
7430
|
+
* approval covers both; the redundant second approval is skipped.
|
|
7431
|
+
*
|
|
7432
|
+
* @typeParam TFromAdapterCapabilities - The source adapter's capabilities.
|
|
7433
|
+
* @param params - The burn amount, executor, hookData, signed-quote claim, and fee.
|
|
7434
|
+
* @returns The prepared approvals, the prepared burn, and the resolved fee plan.
|
|
7435
|
+
* @throws {KitError} If the wallet context is invalid, `destinationChain` does not
|
|
7436
|
+
* support CCTP v2, the executor is missing, `amount` or `feeTotalAmount` is not
|
|
7437
|
+
* a bigint or a numeric string coercible to bigint, the hookData lacks a
|
|
7438
|
+
* `cctp-forward` frame (guaranteed `ForwardFeeWithoutHook`), or the operation
|
|
7439
|
+
* context cannot be resolved.
|
|
7440
|
+
*
|
|
7441
|
+
* @example
|
|
7442
|
+
* ```typescript
|
|
7443
|
+
* const { approvals, burn } = await provider.burnWithFees({
|
|
7444
|
+
* source,
|
|
7445
|
+
* destinationChain: Arc,
|
|
7446
|
+
* amount: 1_000_000n,
|
|
7447
|
+
* executor: genericExecutorAddress,
|
|
7448
|
+
* hookData: geForwardHookData,
|
|
7449
|
+
* claim: { signedQuote: '0x01...', refundAddress: userAddress },
|
|
7450
|
+
* feeToken: '0x0000000000000000000000000000000000000000', // native
|
|
7451
|
+
* feeTotalAmount: 3_500_000n,
|
|
7452
|
+
* })
|
|
7453
|
+
* for (const approval of approvals) await approval.execute()
|
|
7454
|
+
* const txHash = await burn.execute()
|
|
7455
|
+
* ```
|
|
7456
|
+
*/
|
|
7457
|
+
burnWithFees<TFromAdapterCapabilities extends AdapterCapabilities = AdapterCapabilities>(params: BurnWithFeesParams<TFromAdapterCapabilities>): Promise<BurnWithFeesResult>;
|
|
6733
7458
|
/**
|
|
6734
7459
|
* Waits for a transaction to be mined and confirmed on the blockchain.
|
|
6735
7460
|
*
|
|
@@ -6754,164 +7479,5 @@ declare class CCTPV2BridgingProvider extends BridgingProvider<CCTPV2Actions> imp
|
|
|
6754
7479
|
waitForTransaction(adapter: Adapter, txHash: string, chain: ChainDefinition, config?: WaitForTransactionConfig): Promise<WaitForTransactionResponse>;
|
|
6755
7480
|
}
|
|
6756
7481
|
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
*
|
|
6760
|
-
* For EVM chains, the recipient address directly holds ERC20 tokens, so the raw
|
|
6761
|
-
* address is returned as-is. For Solana, USDC is held in Associated Token Accounts
|
|
6762
|
-
* (ATAs), so this function derives the ATA address for the given owner and USDC mint.
|
|
6763
|
-
*
|
|
6764
|
-
* @param chainType - The type of blockchain ('evm' or 'solana').
|
|
6765
|
-
* @param rawAddress - The recipient's wallet address on the destination chain.
|
|
6766
|
-
* @param mint - The USDC mint address (only used for Solana chains).
|
|
6767
|
-
* @returns The address where USDC tokens will be minted (raw address for EVM, ATA for Solana).
|
|
6768
|
-
*
|
|
6769
|
-
* @example
|
|
6770
|
-
* ```typescript
|
|
6771
|
-
* import { getMintRecipientAccount } from './getMintRecipientAccount'
|
|
6772
|
-
*
|
|
6773
|
-
* // EVM: returns the same address
|
|
6774
|
-
* const evmAccount = await getMintRecipientAccount(
|
|
6775
|
-
* 'evm',
|
|
6776
|
-
* '0x742d35Cc6634C0532925a3b8D89C7DA5C3cfa',
|
|
6777
|
-
* 'N/A'
|
|
6778
|
-
* )
|
|
6779
|
-
*
|
|
6780
|
-
* // Solana: derives the Associated Token Account
|
|
6781
|
-
* const solanaAccount = await getMintRecipientAccount(
|
|
6782
|
-
* 'solana',
|
|
6783
|
-
* '9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM',
|
|
6784
|
-
* 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
|
|
6785
|
-
* )
|
|
6786
|
-
* ```
|
|
6787
|
-
*/
|
|
6788
|
-
declare const getMintRecipientAccount: (
|
|
6789
|
-
/** The blockchain type - determines how token accounts are handled */
|
|
6790
|
-
chainType: ChainType,
|
|
6791
|
-
/** The recipient's wallet address (hex format for EVM, base58 for Solana) */
|
|
6792
|
-
rawAddress: string,
|
|
6793
|
-
/** The USDC mint address (ignored for EVM chains, required base58 address for Solana) */
|
|
6794
|
-
mintAddress: string) => Promise<string>;
|
|
6795
|
-
|
|
6796
|
-
/**
|
|
6797
|
-
* Validates and converts a fee value to bigint.
|
|
6798
|
-
*
|
|
6799
|
-
* This utility performs:
|
|
6800
|
-
* 1. Conversion from string or number to bigint
|
|
6801
|
-
* 2. Validation that the value is non-negative
|
|
6802
|
-
*
|
|
6803
|
-
* @param value - The fee value to validate and convert (string or number)
|
|
6804
|
-
* @param fieldName - The name of the field for error messages
|
|
6805
|
-
* @returns The validated fee as a bigint
|
|
6806
|
-
* @throws {KitError} If the value cannot be converted to bigint or is negative
|
|
6807
|
-
*
|
|
6808
|
-
* @example
|
|
6809
|
-
* ```typescript
|
|
6810
|
-
* const fee = validateAndConvertFee('1000000', 'minimumFee')
|
|
6811
|
-
* console.log(fee) // 1000000n
|
|
6812
|
-
*
|
|
6813
|
-
* const fee2 = validateAndConvertFee(500, 'forwardingFee')
|
|
6814
|
-
* console.log(fee2) // 500n
|
|
6815
|
-
* ```
|
|
6816
|
-
*/
|
|
6817
|
-
declare function validateAndConvertFee(value: number | string, fieldName: string): bigint;
|
|
6818
|
-
|
|
6819
|
-
/** A block number value that can be provided as bigint, number, or string. */
|
|
6820
|
-
type BlockNumberInput = bigint | number | string | undefined;
|
|
6821
|
-
/**
|
|
6822
|
-
* Determines whether an attestation has expired based on the current block number.
|
|
6823
|
-
*
|
|
6824
|
-
* An attestation expires when the destination chain's current block number is greater
|
|
6825
|
-
* than or equal to the expiration block specified in the attestation message.
|
|
6826
|
-
* Slow transfers and re-attested messages have `expirationBlock: '0'` and never expire.
|
|
6827
|
-
*
|
|
6828
|
-
* @param attestation - The attestation message containing expiration block information
|
|
6829
|
-
* @param currentBlockNumber - The current block number on the destination chain (bigint, number, or string)
|
|
6830
|
-
* @returns `true` if the attestation has expired, `false` if still valid or never expires
|
|
6831
|
-
* @throws KitError If currentBlockNumber or expirationBlock is invalid
|
|
6832
|
-
*
|
|
6833
|
-
* @example
|
|
6834
|
-
* ```typescript
|
|
6835
|
-
* import { isAttestationExpired } from '@circle-fin/cctp-v2-provider'
|
|
6836
|
-
*
|
|
6837
|
-
* // Check if attestation is expired on EVM chain
|
|
6838
|
-
* const publicClient = await adapter.getPublicClient(destinationChain)
|
|
6839
|
-
* const currentBlock = await publicClient.getBlockNumber()
|
|
6840
|
-
* const expired = isAttestationExpired(attestation, currentBlock)
|
|
6841
|
-
*
|
|
6842
|
-
* if (expired) {
|
|
6843
|
-
* const freshAttestation = await provider.reAttest(source, burnTxHash)
|
|
6844
|
-
* }
|
|
6845
|
-
* ```
|
|
6846
|
-
*
|
|
6847
|
-
* @example
|
|
6848
|
-
* ```typescript
|
|
6849
|
-
* // Check on Solana
|
|
6850
|
-
* const slot = await adapter.getConnection(destinationChain).getSlot()
|
|
6851
|
-
* const expired = isAttestationExpired(attestation, slot)
|
|
6852
|
-
* ```
|
|
6853
|
-
*/
|
|
6854
|
-
declare const isAttestationExpired: (attestation: AttestationMessage, currentBlockNumber: BlockNumberInput) => boolean;
|
|
6855
|
-
/**
|
|
6856
|
-
* Calculates the number of blocks remaining until an attestation expires.
|
|
6857
|
-
*
|
|
6858
|
-
* Returns the difference between the expiration block and the current block number.
|
|
6859
|
-
* Returns `null` if the attestation has `expirationBlock: '0'` (never expires).
|
|
6860
|
-
* Returns `0n` or a negative bigint if the attestation has already expired.
|
|
6861
|
-
*
|
|
6862
|
-
* @param attestation - The attestation message containing expiration block information
|
|
6863
|
-
* @param currentBlockNumber - The current block number on the destination chain (bigint, number, or string)
|
|
6864
|
-
* @returns The number of blocks until expiry as a bigint, or `null` if the attestation never expires
|
|
6865
|
-
* @throws KitError If currentBlockNumber or expirationBlock is invalid
|
|
6866
|
-
*
|
|
6867
|
-
* @example
|
|
6868
|
-
* ```typescript
|
|
6869
|
-
* import { getBlocksUntilExpiry } from '@circle-fin/cctp-v2-provider'
|
|
6870
|
-
*
|
|
6871
|
-
* const publicClient = await adapter.getPublicClient(destinationChain)
|
|
6872
|
-
* const currentBlock = await publicClient.getBlockNumber()
|
|
6873
|
-
* const blocksRemaining = getBlocksUntilExpiry(attestation, currentBlock)
|
|
6874
|
-
*
|
|
6875
|
-
* if (blocksRemaining === null) {
|
|
6876
|
-
* console.log('Attestation never expires')
|
|
6877
|
-
* } else if (blocksRemaining <= 0n) {
|
|
6878
|
-
* console.log('Attestation has expired')
|
|
6879
|
-
* } else {
|
|
6880
|
-
* console.log(`${blocksRemaining} blocks until expiry`)
|
|
6881
|
-
* }
|
|
6882
|
-
* ```
|
|
6883
|
-
*/
|
|
6884
|
-
declare const getBlocksUntilExpiry: (attestation: AttestationMessage, currentBlockNumber: BlockNumberInput) => bigint | null;
|
|
6885
|
-
/**
|
|
6886
|
-
* Determines whether a mint failure was caused by an expired attestation.
|
|
6887
|
-
*
|
|
6888
|
-
* This function inspects the error thrown during a mint operation to detect
|
|
6889
|
-
* if the failure is due to the attestation's expiration block being exceeded.
|
|
6890
|
-
* When this returns `true`, the caller should use `reAttest()` to obtain a
|
|
6891
|
-
* fresh attestation before retrying the mint.
|
|
6892
|
-
*
|
|
6893
|
-
* @param error - The error thrown during the mint operation
|
|
6894
|
-
* @returns `true` if the error indicates the attestation has expired, `false` otherwise
|
|
6895
|
-
*
|
|
6896
|
-
* @example
|
|
6897
|
-
* ```typescript
|
|
6898
|
-
* import { isMintFailureRelatedToAttestation } from '@circle-fin/cctp-v2-provider'
|
|
6899
|
-
*
|
|
6900
|
-
* try {
|
|
6901
|
-
* await mintRequest.execute()
|
|
6902
|
-
* } catch (error) {
|
|
6903
|
-
* if (isMintFailureRelatedToAttestation(error)) {
|
|
6904
|
-
* // Attestation expired - get a fresh one
|
|
6905
|
-
* const freshAttestation = await provider.reAttest(source, burnTxHash)
|
|
6906
|
-
* const newMintRequest = await provider.mint(source, destination, freshAttestation)
|
|
6907
|
-
* await newMintRequest.execute()
|
|
6908
|
-
* } else {
|
|
6909
|
-
* throw error
|
|
6910
|
-
* }
|
|
6911
|
-
* }
|
|
6912
|
-
* ```
|
|
6913
|
-
*/
|
|
6914
|
-
declare const isMintFailureRelatedToAttestation: (error: unknown) => boolean;
|
|
6915
|
-
|
|
6916
|
-
export { CCTPV2BridgingProvider, getBlocksUntilExpiry, getMintRecipientAccount, isAttestationExpired, isMintFailureRelatedToAttestation, validateAndConvertFee };
|
|
6917
|
-
export type { CCTPV2Config };
|
|
7482
|
+
export { CCTPV2BridgingProvider, PREPAID_FORWARD_REVERT_NAMES, assertForwardHookData, getBlocksUntilExpiry, getMintRecipientAccount, hasForwardHook, isAttestationExpired, isMintFailureRelatedToAttestation, mapPrepaidForwardError, resolveFeePayment, validateAndConvertFee };
|
|
7483
|
+
export type { BurnWithFeesParams, BurnWithFeesResult, CCTPV2Config, FeeApproval, FeePaymentPlan, PrepaidForwardRevertName, ResolveFeePaymentParams };
|