@circle-fin/app-kit 1.17.0 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4536,14 +4536,14 @@ var BorrowChain;
4536
4536
  symbol: 'USDC',
4537
4537
  // Arc uses native USDC with 18 decimals for gas payments (EVM standard).
4538
4538
  // Note: The ERC-20 USDC contract at usdcAddress uses 6 decimals.
4539
- // See: https://docs.arc.network/arc/references/contract-addresses
4539
+ // See: https://docs.arc.io/arc/references/contract-addresses
4540
4540
  decimals: 18
4541
4541
  },
4542
4542
  chainId: 5042002,
4543
4543
  isTestnet: true,
4544
4544
  explorerUrl: 'https://testnet.arcscan.app/tx/{hash}',
4545
4545
  rpcEndpoints: [
4546
- 'https://rpc.testnet.arc.network/'
4546
+ 'https://rpc.testnet.arc.io'
4547
4547
  ],
4548
4548
  eurcAddress: '0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a',
4549
4549
  usdcAddress: '0x3600000000000000000000000000000000000000',
@@ -12180,6 +12180,39 @@ function resolveOptions(options) {
12180
12180
  }
12181
12181
  };
12182
12182
  }
12183
+ /**
12184
+ * Emit telemetry for a completed operation without affecting its caller.
12185
+ *
12186
+ * No-ops when `config.disabled` is `true`. Like {@link withErrorTelemetry},
12187
+ * failures while constructing or submitting the telemetry payload are reported
12188
+ * as a soft warning and never change a completed operation's result.
12189
+ *
12190
+ * @param eventType - The telemetry event type for the completed operation.
12191
+ * @param config - Per-kit SDK identity and disabled flag.
12192
+ * @param context - Optional chain, token, and transaction context.
12193
+ * @returns Nothing.
12194
+ * @throws Never — telemetry failures are reported as warnings.
12195
+ *
12196
+ * @example
12197
+ * ```typescript
12198
+ * import { emitSuccessTelemetry } from '@core/utils'
12199
+ *
12200
+ * emitSuccessTelemetry(
12201
+ * 'bridge_bridge',
12202
+ * { sdkName: 'bridge-kit', sdkVersion: '1.0.0', disabled: false },
12203
+ * { sourceChain: 'Ethereum', destinationChain: 'Base', tokenIn: 'USDC' },
12204
+ * )
12205
+ * ```
12206
+ */ function emitSuccessTelemetry(eventType, config, context) {
12207
+ if (config.disabled) {
12208
+ return;
12209
+ }
12210
+ try {
12211
+ void emitAnalyticsLog(buildPayload(config, eventType, undefined, context));
12212
+ } catch (telemetryError) {
12213
+ warnTelemetryDrop(eventType, telemetryError);
12214
+ }
12215
+ }
12183
12216
  /**
12184
12217
  * Wrap an async operation with error telemetry.
12185
12218
  *
@@ -12290,7 +12323,7 @@ function resolveOptions(options) {
12290
12323
  }
12291
12324
 
12292
12325
  var name$3 = "@circle-fin/bridge-kit";
12293
- var version$4 = "1.15.3";
12326
+ var version$4 = "1.16.0";
12294
12327
  var pkg$4 = {
12295
12328
  name: name$3,
12296
12329
  version: version$4};
@@ -13551,6 +13584,53 @@ const EURC_MAINNET_TOKEN_ID = '0x6ca9e29fa53becc29becaf4a90b9ca7a995ad4d2234880d
13551
13584
  }
13552
13585
  };
13553
13586
 
13587
+ /**
13588
+ * Map a CCTPx bytes32 token id back to its known display symbol.
13589
+ *
13590
+ * The inverse of the provider's internal symbol -> id resolution: a bridge
13591
+ * resolves a symbol such as `'cirBTC'` to its canonical bytes32 id and reports
13592
+ * that id on `result.token`, dropping the symbol. This helper recovers the
13593
+ * symbol for display. It is scoped to {@link KNOWN_TOKEN_SYMBOLS} — the same
13594
+ * known set the forward resolution covers — and is keyed by network, because a
13595
+ * symbol names a separate registration on each network, whose ids are
13596
+ * unrelated.
13597
+ *
13598
+ * The lookup is best-effort by design: an arbitrary registry token, a
13599
+ * non-canonical bridge of a known symbol, or any unrecognized id has no known
13600
+ * symbol and yields `undefined`. The id is matched case-insensitively (bytes32
13601
+ * ids have no checksum casing).
13602
+ *
13603
+ * @param id - The bytes32 token id to decode (e.g. a `result.token` value).
13604
+ * @param network - The network the id belongs to (`'testnet'` or `'mainnet'`);
13605
+ * derive it from the source chain, e.g. `chain.isTestnet ? 'testnet' :
13606
+ * 'mainnet'`.
13607
+ * @returns The matching {@link KnownTokenSymbol}, or `undefined` when `id` is
13608
+ * not one of the known canonical ids for `network`.
13609
+ * @throws A `KitError` (`INPUT_VALIDATION_FAILED`, FATAL) when `id` is not a
13610
+ * string or `network` is not a recognized network.
13611
+ *
13612
+ * @example
13613
+ * ```typescript
13614
+ * import { resolveToKnownTokenSymbol } from '@circle-fin/provider-cctpx'
13615
+ *
13616
+ * const result = await provider.bridge(params) // params.token === 'cirBTC'
13617
+ * const network = result.source.chain.isTestnet ? 'testnet' : 'mainnet'
13618
+ *
13619
+ * resolveToKnownTokenSymbol(result.token, network) // 'cirBTC'
13620
+ * resolveToKnownTokenSymbol('0xdeadbeef…', network) // undefined (not known)
13621
+ * ```
13622
+ */ function resolveToKnownTokenSymbol(id, network) {
13623
+ if (typeof id !== 'string') {
13624
+ throw createValidationFailedError$1('id', id, 'must be a string');
13625
+ }
13626
+ if (network !== 'testnet' && network !== 'mainnet') {
13627
+ throw createValidationFailedError$1('network', network, "must be 'testnet' or 'mainnet'");
13628
+ }
13629
+ const row = KNOWN_TOKEN_IDS_BY_NETWORK[network];
13630
+ const target = id.toLowerCase();
13631
+ return KNOWN_TOKEN_SYMBOLS.find((symbol)=>row[symbol].toLowerCase() === target);
13632
+ }
13633
+
13554
13634
  /**
13555
13635
  * Default clock implementation.
13556
13636
  *
@@ -20735,6 +20815,24 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
20735
20815
  }
20736
20816
  };
20737
20817
 
20818
+ /**
20819
+ * Check whether a forwarded burn to the given destination asks Circle's
20820
+ * Forwarding Service to set up the recipient's token account before minting.
20821
+ *
20822
+ * Must return `true` exactly for the destinations where
20823
+ * {@link getForwarderHookData} emits the `createAta` frame, so the forwarding
20824
+ * fee quote includes the setup rent whenever the burn requests it.
20825
+ *
20826
+ * @internal
20827
+ * @param chainType - The destination blockchain type.
20828
+ * @returns `true` for Solana destinations, `false` otherwise.
20829
+ *
20830
+ * @example
20831
+ * ```typescript
20832
+ * requiresRecipientSetup('solana') // true
20833
+ * requiresRecipientSetup('evm') // false
20834
+ * ```
20835
+ */ const requiresRecipientSetup = (chainType)=>chainType === 'solana';
20738
20836
  /**
20739
20837
  * Build the forwarding `hookData` for a forwarded (Orbit-relayed) CCTP v2 burn,
20740
20838
  * tailored to the destination chain.
@@ -21085,10 +21183,12 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
21085
21183
  * @param sourceDomain - The source domain
21086
21184
  * @param destinationDomain - The destination domain
21087
21185
  * @param isTestnet - Whether the request is for a testnet chain
21186
+ * @param includeRecipientSetup - Whether the quote includes recipient account setup rent
21088
21187
  * @returns The complete API URL with forward=true query parameter
21089
- */ function buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet) {
21188
+ */ function buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet, includeRecipientSetup) {
21090
21189
  const baseUrl = isTestnet ? IRIS_API_SANDBOX_BASE_URL$1 : IRIS_API_BASE_URL$1;
21091
- return `${baseUrl}/v2/burn/USDC/fees/${sourceDomain.toString()}/${destinationDomain.toString()}?forward=true`;
21190
+ const recipientSetupQuery = includeRecipientSetup ? '&includeRecipientSetup=true' : '';
21191
+ return `${baseUrl}/v2/burn/USDC/fees/${sourceDomain.toString()}/${destinationDomain.toString()}?forward=true${recipientSetupQuery}`;
21092
21192
  }
21093
21193
  /**
21094
21194
  * Fetches the forwarding fee for a USDC transfer operation with retry and timeout handling.
@@ -21105,6 +21205,10 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
21105
21205
  *
21106
21206
  * The high fee tier is always used to provide buffer for destination gas fluctuations.
21107
21207
  *
21208
+ * Pass `includeRecipientSetup: true` when the burn asks the Forwarding Service to create
21209
+ * the recipient's token account (Solana destinations). The quote then includes the
21210
+ * account rent, which the quote without this flag leaves out.
21211
+ *
21108
21212
  * Implements timeout and retry logic to handle network issues and temporary API failures.
21109
21213
  * Each HTTP request is given a maximum of 2 seconds before it is aborted.
21110
21214
  * We retry up to 10 times, waiting 200ms between attempts.
@@ -21113,6 +21217,8 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
21113
21217
  * @param destinationDomain - The destination domain
21114
21218
  * @param isTestnet - Whether the request is for a testnet chain
21115
21219
  * @param finalityThreshold - The finality threshold to select the fee tier (1000 for FAST, 2000 for SLOW)
21220
+ * @param includeRecipientSetup - Whether to include recipient account setup rent in the
21221
+ * quote. Defaults to `false`.
21116
21222
  * @returns The high-tier forwarding fee in USDC minor units (6 decimals)
21117
21223
  * @throws Error if the input domains are invalid, the API request fails, returns invalid data, or network errors occur
21118
21224
  *
@@ -21124,8 +21230,11 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
21124
21230
  *
21125
21231
  * // SLOW transfer - use 2000ms finality threshold
21126
21232
  * const slowForwardingFee = await fetchForwardingFee(0, 6, false, 2000)
21233
+ *
21234
+ * // Ethereum -> Solana: include the recipient token account rent
21235
+ * const solanaForwardingFee = await fetchForwardingFee(0, 5, false, 1000, true)
21127
21236
  * ```
21128
- */ async function fetchForwardingFee(sourceDomain, destinationDomain, isTestnet, finalityThreshold) {
21237
+ */ async function fetchForwardingFee(sourceDomain, destinationDomain, isTestnet, finalityThreshold, includeRecipientSetup = false) {
21129
21238
  // Validate source domain
21130
21239
  if (!Number.isInteger(sourceDomain) || sourceDomain < 0) {
21131
21240
  throw new KitError({
@@ -21153,7 +21262,7 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
21153
21262
  });
21154
21263
  }
21155
21264
  // Fetch the fee tiers from the API with forward=true
21156
- const url = buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet);
21265
+ const url = buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet, includeRecipientSetup);
21157
21266
  const response = await pollApiGet(url, isForwardingFeeResponse, DEFAULT_CONFIG$1);
21158
21267
  // Validate that we have at least one fee tier
21159
21268
  if (response.length === 0) {
@@ -23489,7 +23598,7 @@ const mockAttestationMessage = {
23489
23598
  return step;
23490
23599
  }
23491
23600
 
23492
- var version$3 = "1.14.2";
23601
+ var version$3 = "1.14.3";
23493
23602
  var pkg$3 = {
23494
23603
  version: version$3};
23495
23604
 
@@ -24408,9 +24517,34 @@ function assertCCTPV2Config(config) {
24408
24517
  tokenAddress: source.chain.usdcAddress,
24409
24518
  operationContext: sourceOperationContext
24410
24519
  });
24520
+ await this.assertAmountCoversRecipientSetupFee(params);
24411
24521
  return bridge(params, this);
24412
24522
  }
24413
24523
  /**
24524
+ * Reject a forwarded transfer to Solana whose amount does not exceed the fee.
24525
+ *
24526
+ * CCTP v2 reverts a burn whose `maxFee` is not less than its amount, and the Solana
24527
+ * forwarding fee includes the recipient token account rent. Checking before the
24528
+ * approval avoids sending a transaction that can never be followed by a burn.
24529
+ * Skipped when the caller provides `config.maxFee`.
24530
+ *
24531
+ * @param params - The validated CCTP v2 bridge parameters.
24532
+ * @returns A promise that resolves when the amount covers the fee.
24533
+ * @throws {KitError} INPUT_INVALID_AMOUNT (FATAL) when the fee is greater than or equal
24534
+ * to the amount.
24535
+ */ async assertAmountCoversRecipientSetupFee(params) {
24536
+ const { destination, amount, config } = params;
24537
+ if (destination.useForwarder !== true || config.maxFee !== undefined || !requiresRecipientSetup(destination.chain.type)) {
24538
+ return;
24539
+ }
24540
+ const { providerFee, forwarderFee } = await this.getMaxFee(params);
24541
+ const maxFee = providerFee + forwarderFee;
24542
+ if (maxFee >= BigInt(amount)) {
24543
+ // Amounts and fees are in USDC minor units (6 decimals)
24544
+ throw createInvalidAmountError(formatUnits(amount, 6), `Amount must be greater than the ${formatUnits(String(maxFee), 6)} USDC fee for forwarded transfers to ${destination.chain.name}, which includes creating the recipient's token account`);
24545
+ }
24546
+ }
24547
+ /**
24414
24548
  * Retry a failed or incomplete CCTP v2 bridge operation.
24415
24549
  *
24416
24550
  * Analyzes the bridge result to determine where to continue and executes
@@ -25127,6 +25261,9 @@ function assertCCTPV2Config(config) {
25127
25261
  * | FAST | true | No | maxFee = calculatedBurnFee + forwardingFee |
25128
25262
  * | FAST | true | Yes | maxFee = config.maxFee |
25129
25263
  *
25264
+ * For forwarded burns to Solana, the forwarding fee includes the rent for creating the
25265
+ * recipient's token account. A caller-provided `maxFee` must cover it too.
25266
+ *
25130
25267
  * @param params - The bridge parameters object containing:
25131
25268
  * - `source`: The source wallet context with chain definition and adapter
25132
25269
  * - `destination`: The destination wallet context with chain definition and adapter
@@ -25165,6 +25302,7 @@ function assertCCTPV2Config(config) {
25165
25302
  }
25166
25303
  // Get the min finality threshold based on the transfer speed
25167
25304
  const minFinalityThreshold = CCTPv2MinFinalityThreshold[transferSpeed];
25305
+ const includeRecipientSetup = requiresRecipientSetup(destination.chain.type);
25168
25306
  // SLOW transfer without forwarder: no fee
25169
25307
  if (transferSpeed === TransferSpeed.SLOW && !useForwarder) {
25170
25308
  return {
@@ -25174,7 +25312,7 @@ function assertCCTPV2Config(config) {
25174
25312
  }
25175
25313
  // SLOW transfer with forwarder: only forwarding fee
25176
25314
  if (transferSpeed === TransferSpeed.SLOW && useForwarder) {
25177
- const forwarderFee = await fetchForwardingFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet, minFinalityThreshold);
25315
+ const forwarderFee = await fetchForwardingFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet, minFinalityThreshold, includeRecipientSetup);
25178
25316
  return {
25179
25317
  providerFee: 0n,
25180
25318
  forwarderFee
@@ -25184,7 +25322,7 @@ function assertCCTPV2Config(config) {
25184
25322
  // Fetch fees in parallel when forwarder is enabled
25185
25323
  const [scaledBps, forwarderFee] = await Promise.all([
25186
25324
  fetchUsdcFastBurnFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet),
25187
- useForwarder ? fetchForwardingFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet, minFinalityThreshold) : Promise.resolve(0n)
25325
+ useForwarder ? fetchForwardingFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet, minFinalityThreshold, includeRecipientSetup) : Promise.resolve(0n)
25188
25326
  ]);
25189
25327
  // Calculate fee proportional to the transfer amount
25190
25328
  const amountInMinorUnits = BigInt(amount);
@@ -25734,6 +25872,21 @@ function assertCCTPV2Config(config) {
25734
25872
  'bridge_forward'
25735
25873
  ]
25736
25874
  ];
25875
+ /**
25876
+ * Provider step names whose `txHash` is the source-chain transaction that
25877
+ * moves funds into the bridge protocol.
25878
+ *
25879
+ * @remarks
25880
+ * The success event carries this hash so the backend can join it to the
25881
+ * on-chain CCTP / CCTPx event for the same transfer. `burn` is the CCTP v2
25882
+ * step (including batched and source-fee flows); `transfer` is the CCTPx
25883
+ * `CrossChainTokenService` step.
25884
+ *
25885
+ * @internal
25886
+ */ const BRIDGE_SOURCE_TX_STEP_NAMES = [
25887
+ 'burn',
25888
+ 'transfer'
25889
+ ];
25737
25890
 
25738
25891
  /**
25739
25892
  * Base URL for Circle's Quote API (hosted in Iris) on mainnet/production.
@@ -26791,6 +26944,85 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
26791
26944
  }
26792
26945
  return undefined;
26793
26946
  }
26947
+ /**
26948
+ * Pick the source-chain transaction hash from a bridge result.
26949
+ *
26950
+ * Walk the steps from the end and return the hash of the most recent
26951
+ * successful source step (`burn` for CCTP v2, `transfer` for CCTPx). Walking
26952
+ * backwards selects the attempt that landed when a retry appended a new
26953
+ * source step after a failed one.
26954
+ *
26955
+ * @param steps - All steps from the bridge result.
26956
+ * @returns The source transaction hash, or `undefined` if no source step recorded one.
26957
+ *
26958
+ * @internal
26959
+ */ function pickSourceTxHash(steps) {
26960
+ for(let i = steps.length - 1; i >= 0; i--){
26961
+ const step = steps[i];
26962
+ if (step?.txHash != null && step.state === 'success' && BRIDGE_SOURCE_TX_STEP_NAMES.includes(step.name)) {
26963
+ return step.txHash;
26964
+ }
26965
+ }
26966
+ return undefined;
26967
+ }
26968
+ /**
26969
+ * Resolve the token value reported in telemetry.
26970
+ *
26971
+ * CCTPx reports `result.token` as a bytes32 token id, while the backend's
26972
+ * canonical tables key tokens by symbol. Map the canonical id of a known CCTPx
26973
+ * token back to its symbol and pass any other value (USDC, or a registry token
26974
+ * without a known symbol) through unchanged. Registry symbols are not used
26975
+ * because they are not unique across CCTPx tokens. Never throws.
26976
+ *
26977
+ * @param token - The token from a bridge result.
26978
+ * @param sourceChain - The result's source chain; selects testnet or mainnet ids.
26979
+ * @returns The known symbol, or `token` unchanged.
26980
+ *
26981
+ * @internal
26982
+ */ function toTelemetryToken(token, sourceChain) {
26983
+ try {
26984
+ const network = sourceChain.isTestnet ? 'testnet' : 'mainnet';
26985
+ return resolveToKnownTokenSymbol(token, network) ?? token;
26986
+ } catch {
26987
+ return token;
26988
+ }
26989
+ }
26990
+ /**
26991
+ * Emit the `bridge_bridge` success event for a completed transfer.
26992
+ *
26993
+ * No-ops unless `result.state` is `'success'`. Failed results are already
26994
+ * reported by error telemetry. Never throws: a malformed result (for example
26995
+ * from a custom provider) is reported as a telemetry drop warning and the
26996
+ * caller's result is returned unchanged.
26997
+ *
26998
+ * @param result - The human-readable bridge result returned to the caller.
26999
+ * @param config - Analytics telemetry identity, gated by `disableAnalytics`.
27000
+ *
27001
+ * @internal
27002
+ */ function emitBridgeSuccessTelemetry(result, config) {
27003
+ if (config.disabled || result.state !== 'success') {
27004
+ return;
27005
+ }
27006
+ try {
27007
+ const txHash = pickSourceTxHash(result.steps);
27008
+ // `JSON.stringify` turns a non-finite number into `null`, which the logs
27009
+ // endpoint's strict schema rejects along with the whole event.
27010
+ const amountIn = Number.parseFloat(result.amount);
27011
+ emitSuccessTelemetry(BRIDGE_EVENT_TYPES.BRIDGE, config, {
27012
+ sourceChain: result.source.chain.chain,
27013
+ destinationChain: result.destination.chain.chain,
27014
+ tokenIn: toTelemetryToken(result.token, result.source.chain),
27015
+ ...Number.isFinite(amountIn) && {
27016
+ amountIn
27017
+ },
27018
+ ...txHash != null && {
27019
+ txHash
27020
+ }
27021
+ });
27022
+ } catch (telemetryError) {
27023
+ warnTelemetryDrop(BRIDGE_EVENT_TYPES.BRIDGE, telemetryError);
27024
+ }
27025
+ }
26794
27026
  /**
26795
27027
  * BridgeKit caller component for retry and estimate operations.
26796
27028
  */ const BRIDGE_KIT_CALLER = {
@@ -26921,6 +27153,10 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
26921
27153
  /** Whether error telemetry is disabled. */ disableErrorReporting;
26922
27154
  /** Per-kit telemetry identity for shared helpers. */ telemetryConfig;
26923
27155
  /**
27156
+ * Per-kit telemetry identity for success events. Gated by `disableAnalytics`
27157
+ * independently of `disableErrorReporting`.
27158
+ */ analyticsTelemetryConfig;
27159
+ /**
26924
27160
  * Create a new BridgeKit instance.
26925
27161
  *
26926
27162
  * @param config - The configuration containing the CCTPv2 provider
@@ -26947,6 +27183,11 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
26947
27183
  sdkVersion: pkg$4.version,
26948
27184
  disabled: this.disableErrorReporting
26949
27185
  };
27186
+ this.analyticsTelemetryConfig = {
27187
+ sdkName: SDK_NAME,
27188
+ sdkVersion: pkg$4.version,
27189
+ disabled: config.disableAnalytics === true
27190
+ };
26950
27191
  for (const provider of this.providers){
26951
27192
  provider.registerDispatcher(this.actionDispatcher);
26952
27193
  }
@@ -26960,7 +27201,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
26960
27201
  this.actionDispatcher.off(actionOrWildCard, handler);
26961
27202
  }
26962
27203
  async bridge(params) {
26963
- return withErrorTelemetry(async ()=>{
27204
+ const bridgeResult = await withErrorTelemetry(async ()=>{
26964
27205
  // First validate the parameters
26965
27206
  assertBridgeParams(params, bridgeParamsWithChainIdentifierSchema);
26966
27207
  // Then resolve chain definitions (includes adapter chain support validation)
@@ -26997,7 +27238,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
26997
27238
  emitResultStepErrorTelemetry(failedStep, BRIDGE_STEP_EVENT_MAP, BRIDGE_EVENT_TYPES.BRIDGE, this.telemetryConfig, {
26998
27239
  sourceChain: resolveChainName(params.from.chain),
26999
27240
  destinationChain: resolveChainName(params.to.chain),
27000
- tokenIn: params.token,
27241
+ tokenIn: toTelemetryToken(result.token, result.source.chain),
27001
27242
  ...txHash != null && {
27002
27243
  txHash
27003
27244
  }
@@ -27009,6 +27250,8 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
27009
27250
  destinationChain: resolveChainName(params.to.chain),
27010
27251
  tokenIn: params.token
27011
27252
  });
27253
+ emitBridgeSuccessTelemetry(bridgeResult, this.analyticsTelemetryConfig);
27254
+ return bridgeResult;
27012
27255
  }
27013
27256
  /**
27014
27257
  * Retry a failed or incomplete cross-chain USDC bridge operation.
@@ -27079,7 +27322,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
27079
27322
  * )
27080
27323
  * ```
27081
27324
  */ async retry(result, context, invocationMeta) {
27082
- return withErrorTelemetry(async ()=>{
27325
+ const retriedResult = await withErrorTelemetry(async ()=>{
27083
27326
  // Cast the providers list to the wide view here. The tuple
27084
27327
  // type on `this.providers` retains concrete provider types
27085
27328
  // (CCTPv2 narrows `TToken` to `'USDC'`); calling `.retry`
@@ -27107,7 +27350,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
27107
27350
  emitResultStepErrorTelemetry(failedStep, BRIDGE_STEP_EVENT_MAP, BRIDGE_EVENT_TYPES.RETRY, this.telemetryConfig, {
27108
27351
  sourceChain: result.source.chain.chain,
27109
27352
  destinationChain: result.destination.chain.chain,
27110
- tokenIn: result.token,
27353
+ tokenIn: toTelemetryToken(result.token, result.source.chain),
27111
27354
  ...txHash != null && {
27112
27355
  txHash
27113
27356
  }
@@ -27121,8 +27364,16 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
27121
27364
  }, BRIDGE_EVENT_TYPES.RETRY, this.telemetryConfig, {
27122
27365
  sourceChain: result.source.chain.chain,
27123
27366
  destinationChain: result.destination.chain.chain,
27124
- tokenIn: result.token
27367
+ tokenIn: toTelemetryToken(result.token, result.source.chain)
27125
27368
  });
27369
+ // A retry that completes the transfer is the transfer's only success
27370
+ // event, so it reports the same `bridge_bridge` type as `bridge()`. An
27371
+ // input that already succeeded was reported by the call that completed it
27372
+ // (CCTP v2 returns such a result unchanged), so it is not reported again.
27373
+ if (result.state !== 'success') {
27374
+ emitBridgeSuccessTelemetry(retriedResult, this.analyticsTelemetryConfig);
27375
+ }
27376
+ return retriedResult;
27126
27377
  }
27127
27378
  async estimate(params) {
27128
27379
  return withErrorTelemetry(async ()=>{
@@ -27718,6 +27969,9 @@ registerKit(`${pkg$4.name}/${pkg$4.version}`);
27718
27969
  ...context.disableErrorReporting != null && {
27719
27970
  disableErrorReporting: context.disableErrorReporting
27720
27971
  },
27972
+ ...context.disableAnalytics != null && {
27973
+ disableAnalytics: context.disableAnalytics
27974
+ },
27721
27975
  ...context.headers != null && {
27722
27976
  headers: context.headers
27723
27977
  }
@@ -27740,7 +27994,7 @@ registerKit(`${pkg$4.name}/${pkg$4.version}`);
27740
27994
  };
27741
27995
 
27742
27996
  var name$2 = "@circle-fin/swap-kit";
27743
- var version$2 = "1.8.0";
27997
+ var version$2 = "1.8.1";
27744
27998
  var pkg$2 = {
27745
27999
  name: name$2,
27746
28000
  version: version$2};
@@ -30012,7 +30266,7 @@ new Set(Object.values(Blockchain));
30012
30266
  registerKit(`${pkg$2.name}/${pkg$2.version}`);
30013
30267
 
30014
30268
  var name$1 = "@circle-fin/earn-kit";
30015
- var version$1 = "1.9.0";
30269
+ var version$1 = "1.10.0";
30016
30270
  var pkg$1 = {
30017
30271
  name: name$1,
30018
30272
  version: version$1};
@@ -31452,7 +31706,7 @@ function hasCrossChainDepositQuoteShape(params) {
31452
31706
  registerKit(`${pkg$1.name}/${pkg$1.version}`);
31453
31707
 
31454
31708
  var name = "@circle-fin/borrow-kit";
31455
- var version = "1.1.0";
31709
+ var version = "1.1.1";
31456
31710
  var pkg = {
31457
31711
  name: name,
31458
31712
  version: version};
package/estimateSwap.cjs CHANGED
@@ -3895,14 +3895,14 @@ var BorrowChain;
3895
3895
  symbol: 'USDC',
3896
3896
  // Arc uses native USDC with 18 decimals for gas payments (EVM standard).
3897
3897
  // Note: The ERC-20 USDC contract at usdcAddress uses 6 decimals.
3898
- // See: https://docs.arc.network/arc/references/contract-addresses
3898
+ // See: https://docs.arc.io/arc/references/contract-addresses
3899
3899
  decimals: 18
3900
3900
  },
3901
3901
  chainId: 5042002,
3902
3902
  isTestnet: true,
3903
3903
  explorerUrl: 'https://testnet.arcscan.app/tx/{hash}',
3904
3904
  rpcEndpoints: [
3905
- 'https://rpc.testnet.arc.network/'
3905
+ 'https://rpc.testnet.arc.io'
3906
3906
  ],
3907
3907
  eurcAddress: '0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a',
3908
3908
  usdcAddress: '0x3600000000000000000000000000000000000000',
@@ -10848,7 +10848,7 @@ const swapTokenEnumSchema = zod.z.enum([
10848
10848
  }
10849
10849
 
10850
10850
  var name$3 = "@circle-fin/bridge-kit";
10851
- var version$3 = "1.15.3";
10851
+ var version$3 = "1.16.0";
10852
10852
  var pkg$3 = {
10853
10853
  name: name$3,
10854
10854
  version: version$3};
@@ -12503,7 +12503,7 @@ const validateQuoteItemSchema = zod.z.object({
12503
12503
  registerKit(`${pkg$3.name}/${pkg$3.version}`);
12504
12504
 
12505
12505
  var name$2 = "@circle-fin/swap-kit";
12506
- var version$2 = "1.8.0";
12506
+ var version$2 = "1.8.1";
12507
12507
  var pkg$2 = {
12508
12508
  name: name$2,
12509
12509
  version: version$2};
@@ -23176,7 +23176,7 @@ registerKit(`${pkg$2.name}/${pkg$2.version}`);
23176
23176
  };
23177
23177
 
23178
23178
  var name$1 = "@circle-fin/earn-kit";
23179
- var version$1 = "1.9.0";
23179
+ var version$1 = "1.10.0";
23180
23180
  var pkg$1 = {
23181
23181
  name: name$1,
23182
23182
  version: version$1};
@@ -24616,7 +24616,7 @@ function hasCrossChainDepositQuoteShape(params) {
24616
24616
  registerKit(`${pkg$1.name}/${pkg$1.version}`);
24617
24617
 
24618
24618
  var name = "@circle-fin/borrow-kit";
24619
- var version = "1.1.0";
24619
+ var version = "1.1.1";
24620
24620
  var pkg = {
24621
24621
  name: name,
24622
24622
  version: version};
@@ -8466,11 +8466,11 @@ interface AppKitContext {
8466
8466
  */
8467
8467
  actions: Record<'bridge' | 'earn' | 'borrow', Record<string, ((payload: unknown) => void)[]>>;
8468
8468
  /**
8469
- * Disable success analytics for the underlying EarnKit, SwapKit,
8469
+ * Disable success analytics for the underlying BridgeKit, EarnKit, SwapKit,
8470
8470
  * BorrowKit, and UnifiedBalanceKit.
8471
8471
  *
8472
- * When `true`, completed earn, swap, borrow, and unified balance operations
8473
- * will not POST analytics events. This does not disable error reporting; use
8472
+ * When `true`, completed bridge, earn, swap, borrow, and unified balance
8473
+ * operations will not POST analytics events. This does not disable error reporting; use
8474
8474
  * {@link AppKitContext.disableErrorReporting} for that. Defaults to `false`.
8475
8475
  *
8476
8476
  * @defaultValue false
@@ -8466,11 +8466,11 @@ interface AppKitContext {
8466
8466
  */
8467
8467
  actions: Record<'bridge' | 'earn' | 'borrow', Record<string, ((payload: unknown) => void)[]>>;
8468
8468
  /**
8469
- * Disable success analytics for the underlying EarnKit, SwapKit,
8469
+ * Disable success analytics for the underlying BridgeKit, EarnKit, SwapKit,
8470
8470
  * BorrowKit, and UnifiedBalanceKit.
8471
8471
  *
8472
- * When `true`, completed earn, swap, borrow, and unified balance operations
8473
- * will not POST analytics events. This does not disable error reporting; use
8472
+ * When `true`, completed bridge, earn, swap, borrow, and unified balance
8473
+ * operations will not POST analytics events. This does not disable error reporting; use
8474
8474
  * {@link AppKitContext.disableErrorReporting} for that. Defaults to `false`.
8475
8475
  *
8476
8476
  * @defaultValue false
package/estimateSwap.d.ts CHANGED
@@ -8466,11 +8466,11 @@ interface AppKitContext {
8466
8466
  */
8467
8467
  actions: Record<'bridge' | 'earn' | 'borrow', Record<string, ((payload: unknown) => void)[]>>;
8468
8468
  /**
8469
- * Disable success analytics for the underlying EarnKit, SwapKit,
8469
+ * Disable success analytics for the underlying BridgeKit, EarnKit, SwapKit,
8470
8470
  * BorrowKit, and UnifiedBalanceKit.
8471
8471
  *
8472
- * When `true`, completed earn, swap, borrow, and unified balance operations
8473
- * will not POST analytics events. This does not disable error reporting; use
8472
+ * When `true`, completed bridge, earn, swap, borrow, and unified balance
8473
+ * operations will not POST analytics events. This does not disable error reporting; use
8474
8474
  * {@link AppKitContext.disableErrorReporting} for that. Defaults to `false`.
8475
8475
  *
8476
8476
  * @defaultValue false
package/estimateSwap.mjs CHANGED
@@ -3888,14 +3888,14 @@ var BorrowChain;
3888
3888
  symbol: 'USDC',
3889
3889
  // Arc uses native USDC with 18 decimals for gas payments (EVM standard).
3890
3890
  // Note: The ERC-20 USDC contract at usdcAddress uses 6 decimals.
3891
- // See: https://docs.arc.network/arc/references/contract-addresses
3891
+ // See: https://docs.arc.io/arc/references/contract-addresses
3892
3892
  decimals: 18
3893
3893
  },
3894
3894
  chainId: 5042002,
3895
3895
  isTestnet: true,
3896
3896
  explorerUrl: 'https://testnet.arcscan.app/tx/{hash}',
3897
3897
  rpcEndpoints: [
3898
- 'https://rpc.testnet.arc.network/'
3898
+ 'https://rpc.testnet.arc.io'
3899
3899
  ],
3900
3900
  eurcAddress: '0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a',
3901
3901
  usdcAddress: '0x3600000000000000000000000000000000000000',
@@ -10841,7 +10841,7 @@ const swapTokenEnumSchema = z.enum([
10841
10841
  }
10842
10842
 
10843
10843
  var name$3 = "@circle-fin/bridge-kit";
10844
- var version$3 = "1.15.3";
10844
+ var version$3 = "1.16.0";
10845
10845
  var pkg$3 = {
10846
10846
  name: name$3,
10847
10847
  version: version$3};
@@ -12496,7 +12496,7 @@ const validateQuoteItemSchema = z.object({
12496
12496
  registerKit(`${pkg$3.name}/${pkg$3.version}`);
12497
12497
 
12498
12498
  var name$2 = "@circle-fin/swap-kit";
12499
- var version$2 = "1.8.0";
12499
+ var version$2 = "1.8.1";
12500
12500
  var pkg$2 = {
12501
12501
  name: name$2,
12502
12502
  version: version$2};
@@ -23169,7 +23169,7 @@ registerKit(`${pkg$2.name}/${pkg$2.version}`);
23169
23169
  };
23170
23170
 
23171
23171
  var name$1 = "@circle-fin/earn-kit";
23172
- var version$1 = "1.9.0";
23172
+ var version$1 = "1.10.0";
23173
23173
  var pkg$1 = {
23174
23174
  name: name$1,
23175
23175
  version: version$1};
@@ -24609,7 +24609,7 @@ function hasCrossChainDepositQuoteShape(params) {
24609
24609
  registerKit(`${pkg$1.name}/${pkg$1.version}`);
24610
24610
 
24611
24611
  var name = "@circle-fin/borrow-kit";
24612
- var version = "1.1.0";
24612
+ var version = "1.1.1";
24613
24613
  var pkg = {
24614
24614
  name: name,
24615
24615
  version: version};