@circle-fin/provider-cctp-v2 1.0.0 → 1.0.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.
Files changed (5) hide show
  1. package/README.md +4 -2
  2. package/index.cjs.js +273 -109
  3. package/index.d.ts +100 -20
  4. package/index.mjs +273 -110
  5. package/package.json +3 -1
package/README.md CHANGED
@@ -232,8 +232,10 @@ const destAdapter = new ViemAdapter({
232
232
  // Monitor transfer events
233
233
  kit.on('*', (event) => console.log('Event:', event)) // subscribe to all events
234
234
  kit.on('approve', (event) => console.log('Approval:', event.values.txHash))
235
- kit.on('depositForBurn', (event) => console.log('Burn:', event.values.txHash))
236
- kit.on('attestation', (event) => console.log('Burn:', event.attestation))
235
+ kit.on('burn', (event) => console.log('Burn:', event.values.txHash))
236
+ kit.on('fetchAttestation', (event) =>
237
+ console.log('Attestation:', event.values.data),
238
+ )
237
239
  kit.on('mint', (event) => console.log('Mint:', event.values.txHash))
238
240
 
239
241
  // Execute transfer
package/index.cjs.js CHANGED
@@ -54,6 +54,7 @@ var Blockchain;
54
54
  Blockchain["Algorand_Testnet"] = "Algorand_Testnet";
55
55
  Blockchain["Aptos"] = "Aptos";
56
56
  Blockchain["Aptos_Testnet"] = "Aptos_Testnet";
57
+ Blockchain["Arc_Testnet"] = "Arc_Testnet";
57
58
  Blockchain["Arbitrum"] = "Arbitrum";
58
59
  Blockchain["Arbitrum_Sepolia"] = "Arbitrum_Sepolia";
59
60
  Blockchain["Avalanche"] = "Avalanche";
@@ -274,6 +275,48 @@ const BRIDGE_CONTRACT_EVM_TESTNET = '0xC5567a5E3370d4DBfB0540025078e283e36A363d'
274
275
  */
275
276
  const BRIDGE_CONTRACT_EVM_MAINNET = '0xB3FA262d0fB521cc93bE83d87b322b8A23DAf3F0';
276
277
 
278
+ /**
279
+ * Arc Testnet chain definition
280
+ * @remarks
281
+ * This represents the test network for the Arc blockchain,
282
+ * Circle's EVM-compatible Layer-1 designed for stablecoin finance
283
+ * and asset tokenization. Arc uses USDC as the native gas token and
284
+ * features the Malachite Byzantine Fault Tolerant (BFT) consensus
285
+ * engine for sub-second finality.
286
+ */
287
+ const ArcTestnet = defineChain({
288
+ type: 'evm',
289
+ chain: Blockchain.Arc_Testnet,
290
+ name: 'Arc Testnet',
291
+ title: 'ArcTestnet',
292
+ nativeCurrency: {
293
+ name: 'Arc',
294
+ symbol: 'Arc',
295
+ decimals: 18,
296
+ },
297
+ chainId: 5042002,
298
+ isTestnet: true,
299
+ explorerUrl: 'https://testnet.arcscan.app/tx/{hash}',
300
+ rpcEndpoints: ['https://rpc.testnet.arc.network/'],
301
+ eurcAddress: '0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a',
302
+ usdcAddress: '0x3600000000000000000000000000000000000000',
303
+ cctp: {
304
+ domain: 26,
305
+ contracts: {
306
+ v2: {
307
+ type: 'split',
308
+ tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
309
+ messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
310
+ confirmations: 1,
311
+ fastConfirmations: 1,
312
+ },
313
+ },
314
+ },
315
+ kitContracts: {
316
+ bridge: BRIDGE_CONTRACT_EVM_TESTNET,
317
+ },
318
+ });
319
+
277
320
  /**
278
321
  * Arbitrum Mainnet chain definition
279
322
  * @remarks
@@ -1565,26 +1608,26 @@ const Sonic = defineChain({
1565
1608
  });
1566
1609
 
1567
1610
  /**
1568
- * Sonic Blaze Testnet chain definition
1611
+ * Sonic Testnet chain definition
1569
1612
  * @remarks
1570
1613
  * This represents the official test network for the Sonic blockchain.
1571
1614
  */
1572
1615
  const SonicTestnet = defineChain({
1573
1616
  type: 'evm',
1574
1617
  chain: Blockchain.Sonic_Testnet,
1575
- name: 'Sonic Blaze Testnet',
1576
- title: 'Sonic Blaze Testnet',
1618
+ name: 'Sonic Testnet',
1619
+ title: 'Sonic Testnet',
1577
1620
  nativeCurrency: {
1578
1621
  name: 'Sonic',
1579
1622
  symbol: 'S',
1580
1623
  decimals: 18,
1581
1624
  },
1582
- chainId: 57054,
1625
+ chainId: 14601,
1583
1626
  isTestnet: true,
1584
1627
  explorerUrl: 'https://testnet.sonicscan.org/tx/{hash}',
1585
- rpcEndpoints: ['https://rpc.blaze.soniclabs.com'],
1628
+ rpcEndpoints: ['https://rpc.testnet.soniclabs.com'],
1586
1629
  eurcAddress: null,
1587
- usdcAddress: '0xA4879Fed32Ecbef99399e5cbC247E533421C4eC6',
1630
+ usdcAddress: '0x0BA304580ee7c9a980CF72e55f5Ed2E9fd30Bc51',
1588
1631
  cctp: {
1589
1632
  domain: 13,
1590
1633
  contracts: {
@@ -2101,6 +2144,7 @@ var Chains = {
2101
2144
  AptosTestnet: AptosTestnet,
2102
2145
  Arbitrum: Arbitrum,
2103
2146
  ArbitrumSepolia: ArbitrumSepolia,
2147
+ ArcTestnet: ArcTestnet,
2104
2148
  Avalanche: Avalanche,
2105
2149
  AvalancheFuji: AvalancheFuji,
2106
2150
  Base: Base,
@@ -2575,69 +2619,133 @@ class BridgingProvider {
2575
2619
  }
2576
2620
 
2577
2621
  /**
2578
- * Sets and gets the Stablecoin Kits SDK user agent string for HTTP requests.
2579
- *
2580
- * The user agent string is formatted as:
2581
- * name/version (platform)
2582
- *
2583
- * - name: The SDK or kit name, set at runtime.
2584
- * - version: The SDK version, set at runtime.
2585
- * - platform: The runtime environment, e.g., "node/nodeVersion" or "browser/browserName".
2622
+ * Detect the runtime environment and return a shortened identifier.
2586
2623
  *
2587
- * @remarks
2588
- * The kit should call setKitIdentifier(name, version) once at startup.
2589
- * A custom user agent will be automatically added to all HTTP requests made by the SDK.
2590
- * This user agent includes the kit name, version, and platform information to help with
2591
- * debugging and analytics.
2592
- *
2593
- * @example
2594
- * ```typescript
2595
- * setKitIdentifier('bridge-kit', '1.2.3')
2596
- * getUserAgent() // "bridge-kit/1.2.3 (node/18.16.0)"
2597
- * ```
2598
- *
2599
- * @returns The Stablecoin Kits SDK user agent string.
2624
+ * @returns Runtime string, e.g., "node/18", "browser/Chrome", or "unknown"
2600
2625
  */
2601
- let cachedUserAgent;
2602
- function getRuntime() {
2626
+ const getRuntime = () => {
2627
+ // Node.js environment
2603
2628
  if (typeof process !== 'undefined' &&
2604
2629
  typeof process.versions === 'object' &&
2605
2630
  typeof process.versions.node === 'string') {
2606
- return `node/${process.versions.node}`;
2631
+ // Shorten to major version only
2632
+ const majorVersion = process.versions.node.split('.')[0] ?? 'unknown';
2633
+ return `node/${majorVersion}`;
2607
2634
  }
2608
- // Detect browser environment
2635
+ // Browser environment
2609
2636
  if (typeof window !== 'undefined' && typeof navigator !== 'undefined') {
2610
2637
  const userAgent = navigator.userAgent;
2611
2638
  const browserMatchers = {
2612
- 'browser/Edge': (ua) => ua.includes('Edg'),
2613
- 'browser/Chrome': (ua) => ua.includes('Chrome') && !ua.includes('Edg'),
2614
- 'browser/Firefox': (ua) => ua.includes('Firefox'),
2615
- 'browser/Safari': (ua) => ua.includes('Safari') && !ua.includes('Chrome'),
2616
- 'browser/InternetExplorer': (ua) => ua.includes('MSIE') || ua.includes('Trident'),
2617
- 'browser/Opera': (ua) => ua.includes('Opera') || ua.includes('OPR'),
2618
- 'browser/Brave': (ua) => ua.includes('Brave'),
2639
+ Edge: (ua) => ua.includes('Edg'),
2640
+ Chrome: (ua) => ua.includes('Chrome') && !ua.includes('Edg'),
2641
+ Firefox: (ua) => ua.includes('Firefox'),
2642
+ Safari: (ua) => ua.includes('Safari') && !ua.includes('Chrome'),
2643
+ Opera: (ua) => ua.includes('Opera') || ua.includes('OPR'),
2619
2644
  };
2620
2645
  for (const [browserName, matcher] of Object.entries(browserMatchers)) {
2621
2646
  if (matcher(userAgent))
2622
- return browserName;
2647
+ return `browser/${browserName}`;
2623
2648
  }
2624
2649
  return 'browser/unknown';
2625
2650
  }
2626
2651
  return 'unknown';
2627
- }
2652
+ };
2628
2653
  /**
2629
- * Get the user agent string for Stablecoin Kits SDK (universal, sync).
2654
+ * Shorten package names by removing common prefixes.
2630
2655
  *
2631
- * @returns The user agent string, e.g., "bridge-kit/1.2.3 (node/18.16.0)"
2656
+ * @param fullName - Full package name, e.g., "\@circle-fin/bridge-kit"
2657
+ * @returns Shortened name, e.g., "bridge-kit"
2632
2658
  */
2633
- function getUserAgent() {
2634
- if (cachedUserAgent !== undefined)
2635
- return cachedUserAgent;
2636
- const name = 'unknown';
2637
- const version = 'unknown';
2638
- cachedUserAgent = `${name}/${version} (${getRuntime()})`;
2639
- return cachedUserAgent;
2640
- }
2659
+ const shortenPackageName = (fullName) => {
2660
+ return fullName.replace('@circle-fin/', '');
2661
+ };
2662
+ /**
2663
+ * Format a component (name/version) with length optimizations.
2664
+ *
2665
+ * @param nameWithVersion - Component identifier, e.g., "\@circle-fin/bridge-kit/1.2.3"
2666
+ * @returns Formatted component, e.g., "bridge-kit/1.2"
2667
+ */
2668
+ const formatComponent = (nameWithVersion) => {
2669
+ // Find the last / to split name and version
2670
+ // This handles scoped packages like @circle-fin/bridge-kit/1.0.0 correctly
2671
+ const lastSlashIndex = nameWithVersion.lastIndexOf('/');
2672
+ if (lastSlashIndex === -1) {
2673
+ // No version, just a name
2674
+ return shortenPackageName(nameWithVersion);
2675
+ }
2676
+ const name = nameWithVersion.substring(0, lastSlashIndex);
2677
+ const version = nameWithVersion.substring(lastSlashIndex + 1);
2678
+ if (name === '')
2679
+ return '';
2680
+ if (version === '')
2681
+ return shortenPackageName(name);
2682
+ return `${shortenPackageName(name)}/${version}`;
2683
+ };
2684
+ /**
2685
+ * Create a new request context from global state.
2686
+ *
2687
+ * Reads the current external prefix and kit identifier from globalThis.
2688
+ * This is used internally by HTTP utilities.
2689
+ *
2690
+ * @returns A new request context
2691
+ * @internal
2692
+ */
2693
+ const createRequestContext = () => {
2694
+ const context = {};
2695
+ if (typeof globalThis !== 'undefined') {
2696
+ if (globalThis.__STABLECOIN_KITS_EXTERNAL_PREFIX__ !== undefined) {
2697
+ context.externalPrefix = globalThis.__STABLECOIN_KITS_EXTERNAL_PREFIX__;
2698
+ }
2699
+ if (globalThis.__STABLECOIN_KITS_CURRENT_KIT__ !== undefined) {
2700
+ context.kit = globalThis.__STABLECOIN_KITS_CURRENT_KIT__;
2701
+ }
2702
+ }
2703
+ return context;
2704
+ };
2705
+ /**
2706
+ * Build a user agent string from a request context.
2707
+ *
2708
+ * Formats the context into a user agent string with automatic optimizations
2709
+ * (shortened package names and truncated versions). The current implementation
2710
+ * tracks a single kit globally.
2711
+ *
2712
+ * Format: `[external-prefix] kit (runtime)`
2713
+ *
2714
+ * @param context - Request context or undefined to use the global context
2715
+ * @returns Formatted user agent string
2716
+ *
2717
+ * @example
2718
+ * ```typescript
2719
+ * // With application prefix and kit
2720
+ * const ua = getUserAgent(context)
2721
+ * // → "my-app/1.0 bridge-kit/1.2 (node/18)"
2722
+ *
2723
+ * // Kit only (no application prefix set)
2724
+ * const ua = getUserAgent()
2725
+ * // → "bridge-kit/1.2 (node/18)"
2726
+ * ```
2727
+ */
2728
+ const getUserAgent = (context) => {
2729
+ const ctx = createRequestContext();
2730
+ const runtime = getRuntime();
2731
+ // Build user agent string
2732
+ const parts = [];
2733
+ // Add external prefix if set
2734
+ if (ctx.externalPrefix !== undefined) {
2735
+ const formatted = formatComponent(ctx.externalPrefix);
2736
+ if (formatted)
2737
+ parts.push(formatted);
2738
+ }
2739
+ // Add kit if set
2740
+ if (ctx.kit !== undefined) {
2741
+ const formatted = formatComponent(ctx.kit);
2742
+ if (formatted)
2743
+ parts.push(formatted);
2744
+ }
2745
+ // Add runtime
2746
+ parts.push(`(${runtime})`);
2747
+ return parts.join(' ');
2748
+ };
2641
2749
 
2642
2750
  /**
2643
2751
  * Default configuration values for the API polling utility.
@@ -3586,9 +3694,9 @@ const customFeeSchema = zod.z
3586
3694
  * token: 'USDC',
3587
3695
  * config: {
3588
3696
  * transferSpeed: 'FAST',
3589
- * maxFee: '1000000'
3697
+ * maxFee: '1.5', // Decimal format
3590
3698
  * customFee: {
3591
- * value: '1000000',
3699
+ * value: '0.5', // Decimal format
3592
3700
  * recipientAddress: '0x1234567890123456789012345678901234567890'
3593
3701
  * }
3594
3702
  * }
@@ -3615,7 +3723,12 @@ const bridgeParamsSchema = zod.z.object({
3615
3723
  transferSpeed: zod.z.nativeEnum(TransferSpeed).optional(),
3616
3724
  maxFee: zod.z
3617
3725
  .string()
3618
- .regex(/^\d+$/, 'Max fee must be a numeric string')
3726
+ .pipe(createDecimalStringValidator({
3727
+ allowZero: true,
3728
+ regexMessage: 'maxFee must be a numeric string with optional decimal places (e.g., "1", "0.5", "1.5")',
3729
+ attributeName: 'maxFee',
3730
+ maxDecimals: 6,
3731
+ })(zod.z.string()))
3619
3732
  .optional(),
3620
3733
  customFee: customFeeSchema.optional(),
3621
3734
  }),
@@ -3772,8 +3885,8 @@ const CCTPv2MinFinalityThreshold = {
3772
3885
  */
3773
3886
  const DEFAULT_CONFIG = {
3774
3887
  timeout: 2_000, // 2 seconds
3775
- maxRetries: 30 * 20, // 2 seconds * 30 * 20 = 20 minutes (to account for slow transfers maximum time based on confirmations)
3776
- retryDelay: 500,
3888
+ maxRetries: 30 * 20, // 30 * 20 * 2 seconds (from the retry delay) = 20 minutes (to account for slow transfers maximum time based on confirmations)
3889
+ retryDelay: 2_000, // 2 seconds
3777
3890
  headers: {
3778
3891
  'Content-Type': 'application/json',
3779
3892
  },
@@ -4205,6 +4318,10 @@ class KitError extends Error {
4205
4318
  }
4206
4319
  }
4207
4320
 
4321
+ /**
4322
+ * Minimum error code for INPUT type errors.
4323
+ * INPUT errors represent validation failures and invalid parameters.
4324
+ */
4208
4325
  /**
4209
4326
  * Standardized error definitions for INPUT type errors.
4210
4327
  *
@@ -4690,8 +4807,6 @@ async function bridgeApproval({ params, provider, }) {
4690
4807
  adapter: params.source.adapter,
4691
4808
  chain: params.source.chain,
4692
4809
  request: await provider.approve(params.source, approvalAmount),
4693
- // We need to wait for the approval to be confirmed on chain before the transfer can be executed
4694
- confirmations: 2,
4695
4810
  });
4696
4811
  }
4697
4812
 
@@ -4705,8 +4820,8 @@ async function bridgeApproval({ params, provider, }) {
4705
4820
  * @param params - The bridge parameters containing source, destination, amount and optional config
4706
4821
  * @param sourceChain - The source chain definition where the burn will occur
4707
4822
  * @returns Promise resolving to the bridge step with transaction details
4708
- * @throws {ValidationError} If the parameters are invalid
4709
- * @throws {BridgeError} If the burn transaction fails
4823
+ * @throws \{ValidationError\} If the parameters are invalid
4824
+ * @throws \{BridgeError\} If the burn transaction fails
4710
4825
  *
4711
4826
  * @example
4712
4827
  * ```typescript
@@ -4715,16 +4830,11 @@ async function bridgeApproval({ params, provider, }) {
4715
4830
  * ```
4716
4831
  */
4717
4832
  async function bridgeBurn({ params, provider, }) {
4718
- const transferSpeed = params.config?.transferSpeed ?? TransferSpeed.FAST;
4719
4833
  return await executePreparedChainRequest({
4720
4834
  name: 'burn',
4721
4835
  adapter: params.source.adapter,
4722
4836
  chain: params.source.chain,
4723
4837
  request: await provider.burn(params),
4724
- confirmations: transferSpeed === TransferSpeed.FAST
4725
- ? params.source.chain.cctp.contracts.v2.fastConfirmations
4726
- : params.source.chain.cctp.contracts.v2.confirmations,
4727
- timeout: transferSpeed === TransferSpeed.FAST ? undefined : 1_200_000, // 20 minutes (max timeout for cctpv2 slow transfers)
4728
4838
  });
4729
4839
  }
4730
4840
 
@@ -4736,16 +4846,18 @@ async function bridgeBurn({ params, provider, }) {
4736
4846
  * and authorizes the minting of equivalent tokens.
4737
4847
  *
4738
4848
  * @param params - The bridge parameters containing source, destination, amount and optional config
4739
- * @param sourceChain - The source chain definition where the burn occurred
4740
- * @param burnTransactionHash - The hash of the burn transaction
4741
- * @returns Promise resolving to the bridge step with transaction details
4742
- * @throws {ValidationError} If the parameters are invalid
4743
- * @throws {BridgeError} If the attestation fetch fails
4849
+ * @param txHash - The hash of the burn transaction
4850
+ * @returns Promise resolving to the bridge step with attestation data
4851
+ * @throws \{ValidationError\} If the parameters are invalid
4852
+ * @throws \{BridgeError\} If the attestation fetch fails
4744
4853
  *
4745
4854
  * @example
4746
4855
  * ```typescript
4747
- * const attestationStep = await fetchAttestation(params, sourceChain, burnTxHash)
4748
- * console.log('Attestation:', attestationStep.attestation)
4856
+ * const attestationStep = await bridgeFetchAttestation(
4857
+ * { params, provider },
4858
+ * burnTxHash
4859
+ * )
4860
+ * console.log('Attestation data:', attestationStep.data)
4749
4861
  * ```
4750
4862
  */
4751
4863
  async function bridgeFetchAttestation({ params, provider, }, txHash) {
@@ -4754,7 +4866,17 @@ async function bridgeFetchAttestation({ params, provider, }, txHash) {
4754
4866
  state: 'pending',
4755
4867
  };
4756
4868
  try {
4757
- const attestation = await provider.fetchAttestation(params.source, txHash);
4869
+ /**
4870
+ * Give slow transfers a longer retry delay of 30 seconds to account for the longer time it takes to get the
4871
+ * attestation so that we do not hit the rate limit of the IRIS API or the retry limit of the API polling utility.
4872
+ * We only do this for slow transfers on source chains that have greater than 20 confirmations (5 minutes of blocktime
4873
+ * on the slowest blocktime chains) so that we do not slow down the attestation polling for lower confirmation chains.
4874
+ */
4875
+ const apiPollingConfig = params.config?.transferSpeed === TransferSpeed.SLOW &&
4876
+ params.source.chain.cctp.contracts.v2.confirmations > 20
4877
+ ? { retryDelay: 30_000 }
4878
+ : undefined;
4879
+ const attestation = await provider.fetchAttestation(params.source, txHash, apiPollingConfig);
4758
4880
  step = {
4759
4881
  ...step,
4760
4882
  state: 'success',
@@ -4762,10 +4884,18 @@ async function bridgeFetchAttestation({ params, provider, }, txHash) {
4762
4884
  };
4763
4885
  }
4764
4886
  catch (err) {
4887
+ let errorMessage = 'Unknown attestation error';
4888
+ if (err instanceof Error) {
4889
+ errorMessage = err.message;
4890
+ }
4891
+ else if (typeof err === 'string') {
4892
+ errorMessage = err;
4893
+ }
4765
4894
  step = {
4766
4895
  ...step,
4767
4896
  state: 'error',
4768
4897
  error: err,
4898
+ errorMessage,
4769
4899
  data: undefined,
4770
4900
  };
4771
4901
  }
@@ -4801,8 +4931,6 @@ async function bridgeMint({ params, provider, }, attestation) {
4801
4931
  adapter: params.destination.adapter,
4802
4932
  chain: params.destination.chain,
4803
4933
  request: await provider.mint(params.source, params.destination, attestation),
4804
- // We will wait for the mint to be confirmed on chain before we will return is as success
4805
- confirmations: 2,
4806
4934
  });
4807
4935
  }
4808
4936
 
@@ -4888,6 +5016,56 @@ function handleStepError(stepName, error, result) {
4888
5016
  });
4889
5017
  }
4890
5018
 
5019
+ /**
5020
+ * Dispatch a bridge step event through the provider's action dispatcher.
5021
+ *
5022
+ * Constructs the appropriate action payload and dispatches it to any registered
5023
+ * event listeners. Handles type-safe dispatching for different step types.
5024
+ *
5025
+ * @param name - The step name (approve, burn, fetchAttestation, or mint).
5026
+ * @param step - The completed bridge step containing transaction details and explorerUrl.
5027
+ * @param provider - The CCTP v2 provider with action dispatcher.
5028
+ *
5029
+ * @example
5030
+ * ```typescript
5031
+ * const step: BridgeStep = {
5032
+ * name: 'burn',
5033
+ * state: 'success',
5034
+ * txHash: '0xabc...',
5035
+ * explorerUrl: 'https://sepolia.etherscan.io/tx/0xabc...',
5036
+ * data: { ... }
5037
+ * }
5038
+ * dispatchStepEvent('burn', step, provider)
5039
+ * ```
5040
+ */
5041
+ function dispatchStepEvent(name, step, provider) {
5042
+ if (!provider.actionDispatcher) {
5043
+ return;
5044
+ }
5045
+ const actionValues = {
5046
+ protocol: 'cctp',
5047
+ version: 'v2',
5048
+ values: step,
5049
+ };
5050
+ switch (name) {
5051
+ case 'approve':
5052
+ case 'burn':
5053
+ case 'mint':
5054
+ provider.actionDispatcher.dispatch(name, {
5055
+ ...actionValues,
5056
+ method: name,
5057
+ });
5058
+ break;
5059
+ case 'fetchAttestation':
5060
+ provider.actionDispatcher.dispatch(name, {
5061
+ ...actionValues,
5062
+ method: name,
5063
+ values: step,
5064
+ });
5065
+ break;
5066
+ }
5067
+ }
5068
+
4891
5069
  /**
4892
5070
  * Execute a cross-chain USDC bridge using the CCTP v2 protocol.
4893
5071
  *
@@ -4944,34 +5122,19 @@ async function bridge(params, provider) {
4944
5122
  try {
4945
5123
  const step = await executor(params, provider, context);
4946
5124
  if (step.state === 'error') {
4947
- // Include error details from the step in the thrown error
4948
- const errorDetails = step.errorMessage ?? 'Unknown error';
5125
+ // Include error details from the step in the thrown error. Fall back to step.error.
5126
+ let fallbackErrorMessage = 'Unknown error';
5127
+ if (step.error instanceof Error) {
5128
+ fallbackErrorMessage = step.error.message;
5129
+ }
5130
+ else if (typeof step.error === 'string') {
5131
+ fallbackErrorMessage = step.error;
5132
+ }
5133
+ const errorDetails = step.errorMessage ?? fallbackErrorMessage;
4949
5134
  throw new Error(`${name} step failed: ${errorDetails}`);
4950
5135
  }
4951
5136
  context = updateContext?.(step);
4952
- const actionValues = {
4953
- protocol: 'cctp',
4954
- version: 'v2',
4955
- values: step,
4956
- };
4957
- // use a switch statement for type safety to separate the different step types
4958
- switch (name) {
4959
- case 'approve':
4960
- case 'burn':
4961
- case 'mint':
4962
- provider.actionDispatcher?.dispatch(name, {
4963
- ...actionValues,
4964
- method: name,
4965
- });
4966
- break;
4967
- case 'fetchAttestation':
4968
- provider.actionDispatcher?.dispatch(name, {
4969
- ...actionValues,
4970
- method: name,
4971
- values: step,
4972
- });
4973
- break;
4974
- }
5137
+ dispatchStepEvent(name, step, provider);
4975
5138
  result.steps.push(step);
4976
5139
  }
4977
5140
  catch (error) {
@@ -5638,12 +5801,7 @@ async function retry(result, context, provider) {
5638
5801
  throw new Error(errorMessage);
5639
5802
  }
5640
5803
  stepContext = updateContext?.(step);
5641
- provider.actionDispatcher?.dispatch(name, {
5642
- protocol: 'cctp',
5643
- version: 'v2',
5644
- method: name,
5645
- values: step.data,
5646
- });
5804
+ dispatchStepEvent(name, step, provider);
5647
5805
  result.steps.push(step);
5648
5806
  }
5649
5807
  catch (error) {
@@ -6212,7 +6370,9 @@ class CCTPV2BridgingProvider extends BridgingProvider {
6212
6370
  * - `source`: The source wallet context with chain definition and adapter
6213
6371
  * - `destination`: The destination wallet context with chain definition and adapter
6214
6372
  * - `amount`: The bridge amount in minor units (e.g., "1000000" for 1 USDC)
6215
- * - `config`: Optional bridge configuration including transferSpeed and maxFee settings
6373
+ * - `config`: Optional bridge configuration including transferSpeed and maxFee settings.
6374
+ * When used via BridgeKit, fee values are automatically converted from human-readable
6375
+ * format (e.g., "1") to smallest units (e.g., "1000000").
6216
6376
  * @returns The maximum fee to be used for the bridge operation in minor units
6217
6377
  *
6218
6378
  * @example
@@ -6220,9 +6380,12 @@ class CCTPV2BridgingProvider extends BridgingProvider {
6220
6380
  * const maxFee = await provider.getMaxFee({
6221
6381
  * source: { adapter: sourceAdapter, chain: Chains.Ethereum, address: '0x...' },
6222
6382
  * destination: { adapter: destAdapter, chain: Chains.Base, address: '0x...' },
6223
- * amount: '1000000', // 1 USDC
6383
+ * amount: '1000000', // 1 USDC in minor units
6224
6384
  * token: 'USDC',
6225
- * config: { transferSpeed: TransferSpeed.FAST }
6385
+ * config: {
6386
+ * transferSpeed: TransferSpeed.FAST,
6387
+ * maxFee: '1000000' // Provider receives values in smallest units
6388
+ * }
6226
6389
  * })
6227
6390
  * console.log('Max fee:', maxFee)
6228
6391
  * ```
@@ -6253,7 +6416,7 @@ class CCTPV2BridgingProvider extends BridgingProvider {
6253
6416
  maxFee = baseFee + baseFee / 10n;
6254
6417
  }
6255
6418
  else {
6256
- // Use the max fee from the config
6419
+ // Use the max fee from the config (converted to minor units by BridgeKit)
6257
6420
  maxFee = BigInt(config.maxFee);
6258
6421
  }
6259
6422
  return maxFee;
@@ -6359,4 +6522,5 @@ class CCTPV2BridgingProvider extends BridgingProvider {
6359
6522
  }
6360
6523
 
6361
6524
  exports.CCTPV2BridgingProvider = CCTPV2BridgingProvider;
6525
+ exports.getMintRecipientAccount = getMintRecipientAccount;
6362
6526
  //# sourceMappingURL=index.cjs.js.map