@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.
package/bridge.cjs CHANGED
@@ -4543,14 +4543,14 @@ var BorrowChain;
4543
4543
  symbol: 'USDC',
4544
4544
  // Arc uses native USDC with 18 decimals for gas payments (EVM standard).
4545
4545
  // Note: The ERC-20 USDC contract at usdcAddress uses 6 decimals.
4546
- // See: https://docs.arc.network/arc/references/contract-addresses
4546
+ // See: https://docs.arc.io/arc/references/contract-addresses
4547
4547
  decimals: 18
4548
4548
  },
4549
4549
  chainId: 5042002,
4550
4550
  isTestnet: true,
4551
4551
  explorerUrl: 'https://testnet.arcscan.app/tx/{hash}',
4552
4552
  rpcEndpoints: [
4553
- 'https://rpc.testnet.arc.network/'
4553
+ 'https://rpc.testnet.arc.io'
4554
4554
  ],
4555
4555
  eurcAddress: '0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a',
4556
4556
  usdcAddress: '0x3600000000000000000000000000000000000000',
@@ -12187,6 +12187,39 @@ function resolveOptions(options) {
12187
12187
  }
12188
12188
  };
12189
12189
  }
12190
+ /**
12191
+ * Emit telemetry for a completed operation without affecting its caller.
12192
+ *
12193
+ * No-ops when `config.disabled` is `true`. Like {@link withErrorTelemetry},
12194
+ * failures while constructing or submitting the telemetry payload are reported
12195
+ * as a soft warning and never change a completed operation's result.
12196
+ *
12197
+ * @param eventType - The telemetry event type for the completed operation.
12198
+ * @param config - Per-kit SDK identity and disabled flag.
12199
+ * @param context - Optional chain, token, and transaction context.
12200
+ * @returns Nothing.
12201
+ * @throws Never — telemetry failures are reported as warnings.
12202
+ *
12203
+ * @example
12204
+ * ```typescript
12205
+ * import { emitSuccessTelemetry } from '@core/utils'
12206
+ *
12207
+ * emitSuccessTelemetry(
12208
+ * 'bridge_bridge',
12209
+ * { sdkName: 'bridge-kit', sdkVersion: '1.0.0', disabled: false },
12210
+ * { sourceChain: 'Ethereum', destinationChain: 'Base', tokenIn: 'USDC' },
12211
+ * )
12212
+ * ```
12213
+ */ function emitSuccessTelemetry(eventType, config, context) {
12214
+ if (config.disabled) {
12215
+ return;
12216
+ }
12217
+ try {
12218
+ void emitAnalyticsLog(buildPayload(config, eventType, undefined, context));
12219
+ } catch (telemetryError) {
12220
+ warnTelemetryDrop(eventType, telemetryError);
12221
+ }
12222
+ }
12190
12223
  /**
12191
12224
  * Wrap an async operation with error telemetry.
12192
12225
  *
@@ -12297,7 +12330,7 @@ function resolveOptions(options) {
12297
12330
  }
12298
12331
 
12299
12332
  var name$3 = "@circle-fin/bridge-kit";
12300
- var version$4 = "1.15.3";
12333
+ var version$4 = "1.16.0";
12301
12334
  var pkg$4 = {
12302
12335
  name: name$3,
12303
12336
  version: version$4};
@@ -13558,6 +13591,53 @@ const EURC_MAINNET_TOKEN_ID = '0x6ca9e29fa53becc29becaf4a90b9ca7a995ad4d2234880d
13558
13591
  }
13559
13592
  };
13560
13593
 
13594
+ /**
13595
+ * Map a CCTPx bytes32 token id back to its known display symbol.
13596
+ *
13597
+ * The inverse of the provider's internal symbol -> id resolution: a bridge
13598
+ * resolves a symbol such as `'cirBTC'` to its canonical bytes32 id and reports
13599
+ * that id on `result.token`, dropping the symbol. This helper recovers the
13600
+ * symbol for display. It is scoped to {@link KNOWN_TOKEN_SYMBOLS} — the same
13601
+ * known set the forward resolution covers — and is keyed by network, because a
13602
+ * symbol names a separate registration on each network, whose ids are
13603
+ * unrelated.
13604
+ *
13605
+ * The lookup is best-effort by design: an arbitrary registry token, a
13606
+ * non-canonical bridge of a known symbol, or any unrecognized id has no known
13607
+ * symbol and yields `undefined`. The id is matched case-insensitively (bytes32
13608
+ * ids have no checksum casing).
13609
+ *
13610
+ * @param id - The bytes32 token id to decode (e.g. a `result.token` value).
13611
+ * @param network - The network the id belongs to (`'testnet'` or `'mainnet'`);
13612
+ * derive it from the source chain, e.g. `chain.isTestnet ? 'testnet' :
13613
+ * 'mainnet'`.
13614
+ * @returns The matching {@link KnownTokenSymbol}, or `undefined` when `id` is
13615
+ * not one of the known canonical ids for `network`.
13616
+ * @throws A `KitError` (`INPUT_VALIDATION_FAILED`, FATAL) when `id` is not a
13617
+ * string or `network` is not a recognized network.
13618
+ *
13619
+ * @example
13620
+ * ```typescript
13621
+ * import { resolveToKnownTokenSymbol } from '@circle-fin/provider-cctpx'
13622
+ *
13623
+ * const result = await provider.bridge(params) // params.token === 'cirBTC'
13624
+ * const network = result.source.chain.isTestnet ? 'testnet' : 'mainnet'
13625
+ *
13626
+ * resolveToKnownTokenSymbol(result.token, network) // 'cirBTC'
13627
+ * resolveToKnownTokenSymbol('0xdeadbeef…', network) // undefined (not known)
13628
+ * ```
13629
+ */ function resolveToKnownTokenSymbol(id, network) {
13630
+ if (typeof id !== 'string') {
13631
+ throw createValidationFailedError$1('id', id, 'must be a string');
13632
+ }
13633
+ if (network !== 'testnet' && network !== 'mainnet') {
13634
+ throw createValidationFailedError$1('network', network, "must be 'testnet' or 'mainnet'");
13635
+ }
13636
+ const row = KNOWN_TOKEN_IDS_BY_NETWORK[network];
13637
+ const target = id.toLowerCase();
13638
+ return KNOWN_TOKEN_SYMBOLS.find((symbol)=>row[symbol].toLowerCase() === target);
13639
+ }
13640
+
13561
13641
  /**
13562
13642
  * Default clock implementation.
13563
13643
  *
@@ -20742,6 +20822,24 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
20742
20822
  }
20743
20823
  };
20744
20824
 
20825
+ /**
20826
+ * Check whether a forwarded burn to the given destination asks Circle's
20827
+ * Forwarding Service to set up the recipient's token account before minting.
20828
+ *
20829
+ * Must return `true` exactly for the destinations where
20830
+ * {@link getForwarderHookData} emits the `createAta` frame, so the forwarding
20831
+ * fee quote includes the setup rent whenever the burn requests it.
20832
+ *
20833
+ * @internal
20834
+ * @param chainType - The destination blockchain type.
20835
+ * @returns `true` for Solana destinations, `false` otherwise.
20836
+ *
20837
+ * @example
20838
+ * ```typescript
20839
+ * requiresRecipientSetup('solana') // true
20840
+ * requiresRecipientSetup('evm') // false
20841
+ * ```
20842
+ */ const requiresRecipientSetup = (chainType)=>chainType === 'solana';
20745
20843
  /**
20746
20844
  * Build the forwarding `hookData` for a forwarded (Orbit-relayed) CCTP v2 burn,
20747
20845
  * tailored to the destination chain.
@@ -21092,10 +21190,12 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
21092
21190
  * @param sourceDomain - The source domain
21093
21191
  * @param destinationDomain - The destination domain
21094
21192
  * @param isTestnet - Whether the request is for a testnet chain
21193
+ * @param includeRecipientSetup - Whether the quote includes recipient account setup rent
21095
21194
  * @returns The complete API URL with forward=true query parameter
21096
- */ function buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet) {
21195
+ */ function buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet, includeRecipientSetup) {
21097
21196
  const baseUrl = isTestnet ? IRIS_API_SANDBOX_BASE_URL$1 : IRIS_API_BASE_URL$1;
21098
- return `${baseUrl}/v2/burn/USDC/fees/${sourceDomain.toString()}/${destinationDomain.toString()}?forward=true`;
21197
+ const recipientSetupQuery = includeRecipientSetup ? '&includeRecipientSetup=true' : '';
21198
+ return `${baseUrl}/v2/burn/USDC/fees/${sourceDomain.toString()}/${destinationDomain.toString()}?forward=true${recipientSetupQuery}`;
21099
21199
  }
21100
21200
  /**
21101
21201
  * Fetches the forwarding fee for a USDC transfer operation with retry and timeout handling.
@@ -21112,6 +21212,10 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
21112
21212
  *
21113
21213
  * The high fee tier is always used to provide buffer for destination gas fluctuations.
21114
21214
  *
21215
+ * Pass `includeRecipientSetup: true` when the burn asks the Forwarding Service to create
21216
+ * the recipient's token account (Solana destinations). The quote then includes the
21217
+ * account rent, which the quote without this flag leaves out.
21218
+ *
21115
21219
  * Implements timeout and retry logic to handle network issues and temporary API failures.
21116
21220
  * Each HTTP request is given a maximum of 2 seconds before it is aborted.
21117
21221
  * We retry up to 10 times, waiting 200ms between attempts.
@@ -21120,6 +21224,8 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
21120
21224
  * @param destinationDomain - The destination domain
21121
21225
  * @param isTestnet - Whether the request is for a testnet chain
21122
21226
  * @param finalityThreshold - The finality threshold to select the fee tier (1000 for FAST, 2000 for SLOW)
21227
+ * @param includeRecipientSetup - Whether to include recipient account setup rent in the
21228
+ * quote. Defaults to `false`.
21123
21229
  * @returns The high-tier forwarding fee in USDC minor units (6 decimals)
21124
21230
  * @throws Error if the input domains are invalid, the API request fails, returns invalid data, or network errors occur
21125
21231
  *
@@ -21131,8 +21237,11 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
21131
21237
  *
21132
21238
  * // SLOW transfer - use 2000ms finality threshold
21133
21239
  * const slowForwardingFee = await fetchForwardingFee(0, 6, false, 2000)
21240
+ *
21241
+ * // Ethereum -> Solana: include the recipient token account rent
21242
+ * const solanaForwardingFee = await fetchForwardingFee(0, 5, false, 1000, true)
21134
21243
  * ```
21135
- */ async function fetchForwardingFee(sourceDomain, destinationDomain, isTestnet, finalityThreshold) {
21244
+ */ async function fetchForwardingFee(sourceDomain, destinationDomain, isTestnet, finalityThreshold, includeRecipientSetup = false) {
21136
21245
  // Validate source domain
21137
21246
  if (!Number.isInteger(sourceDomain) || sourceDomain < 0) {
21138
21247
  throw new KitError({
@@ -21160,7 +21269,7 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
21160
21269
  });
21161
21270
  }
21162
21271
  // Fetch the fee tiers from the API with forward=true
21163
- const url = buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet);
21272
+ const url = buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet, includeRecipientSetup);
21164
21273
  const response = await pollApiGet(url, isForwardingFeeResponse, DEFAULT_CONFIG$1);
21165
21274
  // Validate that we have at least one fee tier
21166
21275
  if (response.length === 0) {
@@ -23496,7 +23605,7 @@ const mockAttestationMessage = {
23496
23605
  return step;
23497
23606
  }
23498
23607
 
23499
- var version$3 = "1.14.2";
23608
+ var version$3 = "1.14.3";
23500
23609
  var pkg$3 = {
23501
23610
  version: version$3};
23502
23611
 
@@ -24415,9 +24524,34 @@ function assertCCTPV2Config(config) {
24415
24524
  tokenAddress: source.chain.usdcAddress,
24416
24525
  operationContext: sourceOperationContext
24417
24526
  });
24527
+ await this.assertAmountCoversRecipientSetupFee(params);
24418
24528
  return bridge$1(params, this);
24419
24529
  }
24420
24530
  /**
24531
+ * Reject a forwarded transfer to Solana whose amount does not exceed the fee.
24532
+ *
24533
+ * CCTP v2 reverts a burn whose `maxFee` is not less than its amount, and the Solana
24534
+ * forwarding fee includes the recipient token account rent. Checking before the
24535
+ * approval avoids sending a transaction that can never be followed by a burn.
24536
+ * Skipped when the caller provides `config.maxFee`.
24537
+ *
24538
+ * @param params - The validated CCTP v2 bridge parameters.
24539
+ * @returns A promise that resolves when the amount covers the fee.
24540
+ * @throws {KitError} INPUT_INVALID_AMOUNT (FATAL) when the fee is greater than or equal
24541
+ * to the amount.
24542
+ */ async assertAmountCoversRecipientSetupFee(params) {
24543
+ const { destination, amount, config } = params;
24544
+ if (destination.useForwarder !== true || config.maxFee !== undefined || !requiresRecipientSetup(destination.chain.type)) {
24545
+ return;
24546
+ }
24547
+ const { providerFee, forwarderFee } = await this.getMaxFee(params);
24548
+ const maxFee = providerFee + forwarderFee;
24549
+ if (maxFee >= BigInt(amount)) {
24550
+ // Amounts and fees are in USDC minor units (6 decimals)
24551
+ 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`);
24552
+ }
24553
+ }
24554
+ /**
24421
24555
  * Retry a failed or incomplete CCTP v2 bridge operation.
24422
24556
  *
24423
24557
  * Analyzes the bridge result to determine where to continue and executes
@@ -25134,6 +25268,9 @@ function assertCCTPV2Config(config) {
25134
25268
  * | FAST | true | No | maxFee = calculatedBurnFee + forwardingFee |
25135
25269
  * | FAST | true | Yes | maxFee = config.maxFee |
25136
25270
  *
25271
+ * For forwarded burns to Solana, the forwarding fee includes the rent for creating the
25272
+ * recipient's token account. A caller-provided `maxFee` must cover it too.
25273
+ *
25137
25274
  * @param params - The bridge parameters object containing:
25138
25275
  * - `source`: The source wallet context with chain definition and adapter
25139
25276
  * - `destination`: The destination wallet context with chain definition and adapter
@@ -25172,6 +25309,7 @@ function assertCCTPV2Config(config) {
25172
25309
  }
25173
25310
  // Get the min finality threshold based on the transfer speed
25174
25311
  const minFinalityThreshold = CCTPv2MinFinalityThreshold[transferSpeed];
25312
+ const includeRecipientSetup = requiresRecipientSetup(destination.chain.type);
25175
25313
  // SLOW transfer without forwarder: no fee
25176
25314
  if (transferSpeed === TransferSpeed.SLOW && !useForwarder) {
25177
25315
  return {
@@ -25181,7 +25319,7 @@ function assertCCTPV2Config(config) {
25181
25319
  }
25182
25320
  // SLOW transfer with forwarder: only forwarding fee
25183
25321
  if (transferSpeed === TransferSpeed.SLOW && useForwarder) {
25184
- const forwarderFee = await fetchForwardingFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet, minFinalityThreshold);
25322
+ const forwarderFee = await fetchForwardingFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet, minFinalityThreshold, includeRecipientSetup);
25185
25323
  return {
25186
25324
  providerFee: 0n,
25187
25325
  forwarderFee
@@ -25191,7 +25329,7 @@ function assertCCTPV2Config(config) {
25191
25329
  // Fetch fees in parallel when forwarder is enabled
25192
25330
  const [scaledBps, forwarderFee] = await Promise.all([
25193
25331
  fetchUsdcFastBurnFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet),
25194
- useForwarder ? fetchForwardingFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet, minFinalityThreshold) : Promise.resolve(0n)
25332
+ useForwarder ? fetchForwardingFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet, minFinalityThreshold, includeRecipientSetup) : Promise.resolve(0n)
25195
25333
  ]);
25196
25334
  // Calculate fee proportional to the transfer amount
25197
25335
  const amountInMinorUnits = BigInt(amount);
@@ -25741,6 +25879,21 @@ function assertCCTPV2Config(config) {
25741
25879
  'bridge_forward'
25742
25880
  ]
25743
25881
  ];
25882
+ /**
25883
+ * Provider step names whose `txHash` is the source-chain transaction that
25884
+ * moves funds into the bridge protocol.
25885
+ *
25886
+ * @remarks
25887
+ * The success event carries this hash so the backend can join it to the
25888
+ * on-chain CCTP / CCTPx event for the same transfer. `burn` is the CCTP v2
25889
+ * step (including batched and source-fee flows); `transfer` is the CCTPx
25890
+ * `CrossChainTokenService` step.
25891
+ *
25892
+ * @internal
25893
+ */ const BRIDGE_SOURCE_TX_STEP_NAMES = [
25894
+ 'burn',
25895
+ 'transfer'
25896
+ ];
25744
25897
 
25745
25898
  /**
25746
25899
  * Base URL for Circle's Quote API (hosted in Iris) on mainnet/production.
@@ -26798,6 +26951,85 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
26798
26951
  }
26799
26952
  return undefined;
26800
26953
  }
26954
+ /**
26955
+ * Pick the source-chain transaction hash from a bridge result.
26956
+ *
26957
+ * Walk the steps from the end and return the hash of the most recent
26958
+ * successful source step (`burn` for CCTP v2, `transfer` for CCTPx). Walking
26959
+ * backwards selects the attempt that landed when a retry appended a new
26960
+ * source step after a failed one.
26961
+ *
26962
+ * @param steps - All steps from the bridge result.
26963
+ * @returns The source transaction hash, or `undefined` if no source step recorded one.
26964
+ *
26965
+ * @internal
26966
+ */ function pickSourceTxHash(steps) {
26967
+ for(let i = steps.length - 1; i >= 0; i--){
26968
+ const step = steps[i];
26969
+ if (step?.txHash != null && step.state === 'success' && BRIDGE_SOURCE_TX_STEP_NAMES.includes(step.name)) {
26970
+ return step.txHash;
26971
+ }
26972
+ }
26973
+ return undefined;
26974
+ }
26975
+ /**
26976
+ * Resolve the token value reported in telemetry.
26977
+ *
26978
+ * CCTPx reports `result.token` as a bytes32 token id, while the backend's
26979
+ * canonical tables key tokens by symbol. Map the canonical id of a known CCTPx
26980
+ * token back to its symbol and pass any other value (USDC, or a registry token
26981
+ * without a known symbol) through unchanged. Registry symbols are not used
26982
+ * because they are not unique across CCTPx tokens. Never throws.
26983
+ *
26984
+ * @param token - The token from a bridge result.
26985
+ * @param sourceChain - The result's source chain; selects testnet or mainnet ids.
26986
+ * @returns The known symbol, or `token` unchanged.
26987
+ *
26988
+ * @internal
26989
+ */ function toTelemetryToken(token, sourceChain) {
26990
+ try {
26991
+ const network = sourceChain.isTestnet ? 'testnet' : 'mainnet';
26992
+ return resolveToKnownTokenSymbol(token, network) ?? token;
26993
+ } catch {
26994
+ return token;
26995
+ }
26996
+ }
26997
+ /**
26998
+ * Emit the `bridge_bridge` success event for a completed transfer.
26999
+ *
27000
+ * No-ops unless `result.state` is `'success'`. Failed results are already
27001
+ * reported by error telemetry. Never throws: a malformed result (for example
27002
+ * from a custom provider) is reported as a telemetry drop warning and the
27003
+ * caller's result is returned unchanged.
27004
+ *
27005
+ * @param result - The human-readable bridge result returned to the caller.
27006
+ * @param config - Analytics telemetry identity, gated by `disableAnalytics`.
27007
+ *
27008
+ * @internal
27009
+ */ function emitBridgeSuccessTelemetry(result, config) {
27010
+ if (config.disabled || result.state !== 'success') {
27011
+ return;
27012
+ }
27013
+ try {
27014
+ const txHash = pickSourceTxHash(result.steps);
27015
+ // `JSON.stringify` turns a non-finite number into `null`, which the logs
27016
+ // endpoint's strict schema rejects along with the whole event.
27017
+ const amountIn = Number.parseFloat(result.amount);
27018
+ emitSuccessTelemetry(BRIDGE_EVENT_TYPES.BRIDGE, config, {
27019
+ sourceChain: result.source.chain.chain,
27020
+ destinationChain: result.destination.chain.chain,
27021
+ tokenIn: toTelemetryToken(result.token, result.source.chain),
27022
+ ...Number.isFinite(amountIn) && {
27023
+ amountIn
27024
+ },
27025
+ ...txHash != null && {
27026
+ txHash
27027
+ }
27028
+ });
27029
+ } catch (telemetryError) {
27030
+ warnTelemetryDrop(BRIDGE_EVENT_TYPES.BRIDGE, telemetryError);
27031
+ }
27032
+ }
26801
27033
  /**
26802
27034
  * BridgeKit caller component for retry and estimate operations.
26803
27035
  */ const BRIDGE_KIT_CALLER = {
@@ -26928,6 +27160,10 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
26928
27160
  /** Whether error telemetry is disabled. */ disableErrorReporting;
26929
27161
  /** Per-kit telemetry identity for shared helpers. */ telemetryConfig;
26930
27162
  /**
27163
+ * Per-kit telemetry identity for success events. Gated by `disableAnalytics`
27164
+ * independently of `disableErrorReporting`.
27165
+ */ analyticsTelemetryConfig;
27166
+ /**
26931
27167
  * Create a new BridgeKit instance.
26932
27168
  *
26933
27169
  * @param config - The configuration containing the CCTPv2 provider
@@ -26954,6 +27190,11 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
26954
27190
  sdkVersion: pkg$4.version,
26955
27191
  disabled: this.disableErrorReporting
26956
27192
  };
27193
+ this.analyticsTelemetryConfig = {
27194
+ sdkName: SDK_NAME,
27195
+ sdkVersion: pkg$4.version,
27196
+ disabled: config.disableAnalytics === true
27197
+ };
26957
27198
  for (const provider of this.providers){
26958
27199
  provider.registerDispatcher(this.actionDispatcher);
26959
27200
  }
@@ -26967,7 +27208,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
26967
27208
  this.actionDispatcher.off(actionOrWildCard, handler);
26968
27209
  }
26969
27210
  async bridge(params) {
26970
- return withErrorTelemetry(async ()=>{
27211
+ const bridgeResult = await withErrorTelemetry(async ()=>{
26971
27212
  // First validate the parameters
26972
27213
  assertBridgeParams(params, bridgeParamsWithChainIdentifierSchema);
26973
27214
  // Then resolve chain definitions (includes adapter chain support validation)
@@ -27004,7 +27245,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
27004
27245
  emitResultStepErrorTelemetry(failedStep, BRIDGE_STEP_EVENT_MAP, BRIDGE_EVENT_TYPES.BRIDGE, this.telemetryConfig, {
27005
27246
  sourceChain: resolveChainName(params.from.chain),
27006
27247
  destinationChain: resolveChainName(params.to.chain),
27007
- tokenIn: params.token,
27248
+ tokenIn: toTelemetryToken(result.token, result.source.chain),
27008
27249
  ...txHash != null && {
27009
27250
  txHash
27010
27251
  }
@@ -27016,6 +27257,8 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
27016
27257
  destinationChain: resolveChainName(params.to.chain),
27017
27258
  tokenIn: params.token
27018
27259
  });
27260
+ emitBridgeSuccessTelemetry(bridgeResult, this.analyticsTelemetryConfig);
27261
+ return bridgeResult;
27019
27262
  }
27020
27263
  /**
27021
27264
  * Retry a failed or incomplete cross-chain USDC bridge operation.
@@ -27086,7 +27329,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
27086
27329
  * )
27087
27330
  * ```
27088
27331
  */ async retry(result, context, invocationMeta) {
27089
- return withErrorTelemetry(async ()=>{
27332
+ const retriedResult = await withErrorTelemetry(async ()=>{
27090
27333
  // Cast the providers list to the wide view here. The tuple
27091
27334
  // type on `this.providers` retains concrete provider types
27092
27335
  // (CCTPv2 narrows `TToken` to `'USDC'`); calling `.retry`
@@ -27114,7 +27357,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
27114
27357
  emitResultStepErrorTelemetry(failedStep, BRIDGE_STEP_EVENT_MAP, BRIDGE_EVENT_TYPES.RETRY, this.telemetryConfig, {
27115
27358
  sourceChain: result.source.chain.chain,
27116
27359
  destinationChain: result.destination.chain.chain,
27117
- tokenIn: result.token,
27360
+ tokenIn: toTelemetryToken(result.token, result.source.chain),
27118
27361
  ...txHash != null && {
27119
27362
  txHash
27120
27363
  }
@@ -27128,8 +27371,16 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
27128
27371
  }, BRIDGE_EVENT_TYPES.RETRY, this.telemetryConfig, {
27129
27372
  sourceChain: result.source.chain.chain,
27130
27373
  destinationChain: result.destination.chain.chain,
27131
- tokenIn: result.token
27374
+ tokenIn: toTelemetryToken(result.token, result.source.chain)
27132
27375
  });
27376
+ // A retry that completes the transfer is the transfer's only success
27377
+ // event, so it reports the same `bridge_bridge` type as `bridge()`. An
27378
+ // input that already succeeded was reported by the call that completed it
27379
+ // (CCTP v2 returns such a result unchanged), so it is not reported again.
27380
+ if (result.state !== 'success') {
27381
+ emitBridgeSuccessTelemetry(retriedResult, this.analyticsTelemetryConfig);
27382
+ }
27383
+ return retriedResult;
27133
27384
  }
27134
27385
  async estimate(params) {
27135
27386
  return withErrorTelemetry(async ()=>{
@@ -27725,6 +27976,9 @@ registerKit(`${pkg$4.name}/${pkg$4.version}`);
27725
27976
  ...context.disableErrorReporting != null && {
27726
27977
  disableErrorReporting: context.disableErrorReporting
27727
27978
  },
27979
+ ...context.disableAnalytics != null && {
27980
+ disableAnalytics: context.disableAnalytics
27981
+ },
27728
27982
  ...context.headers != null && {
27729
27983
  headers: context.headers
27730
27984
  }
@@ -27747,7 +28001,7 @@ registerKit(`${pkg$4.name}/${pkg$4.version}`);
27747
28001
  };
27748
28002
 
27749
28003
  var name$2 = "@circle-fin/swap-kit";
27750
- var version$2 = "1.8.0";
28004
+ var version$2 = "1.8.1";
27751
28005
  var pkg$2 = {
27752
28006
  name: name$2,
27753
28007
  version: version$2};
@@ -30019,7 +30273,7 @@ new Set(Object.values(Blockchain));
30019
30273
  registerKit(`${pkg$2.name}/${pkg$2.version}`);
30020
30274
 
30021
30275
  var name$1 = "@circle-fin/earn-kit";
30022
- var version$1 = "1.9.0";
30276
+ var version$1 = "1.10.0";
30023
30277
  var pkg$1 = {
30024
30278
  name: name$1,
30025
30279
  version: version$1};
@@ -31523,7 +31777,7 @@ registerKit(`${pkg$1.name}/${pkg$1.version}`);
31523
31777
  };
31524
31778
 
31525
31779
  var name = "@circle-fin/borrow-kit";
31526
- var version = "1.1.0";
31780
+ var version = "1.1.1";
31527
31781
  var pkg = {
31528
31782
  name: name,
31529
31783
  version: version};
package/bridge.d.cts CHANGED
@@ -8454,11 +8454,11 @@ interface AppKitContext {
8454
8454
  */
8455
8455
  actions: Record<'bridge' | 'earn' | 'borrow', Record<string, ((payload: unknown) => void)[]>>;
8456
8456
  /**
8457
- * Disable success analytics for the underlying EarnKit, SwapKit,
8457
+ * Disable success analytics for the underlying BridgeKit, EarnKit, SwapKit,
8458
8458
  * BorrowKit, and UnifiedBalanceKit.
8459
8459
  *
8460
- * When `true`, completed earn, swap, borrow, and unified balance operations
8461
- * will not POST analytics events. This does not disable error reporting; use
8460
+ * When `true`, completed bridge, earn, swap, borrow, and unified balance
8461
+ * operations will not POST analytics events. This does not disable error reporting; use
8462
8462
  * {@link AppKitContext.disableErrorReporting} for that. Defaults to `false`.
8463
8463
  *
8464
8464
  * @defaultValue false
package/bridge.d.mts CHANGED
@@ -8454,11 +8454,11 @@ interface AppKitContext {
8454
8454
  */
8455
8455
  actions: Record<'bridge' | 'earn' | 'borrow', Record<string, ((payload: unknown) => void)[]>>;
8456
8456
  /**
8457
- * Disable success analytics for the underlying EarnKit, SwapKit,
8457
+ * Disable success analytics for the underlying BridgeKit, EarnKit, SwapKit,
8458
8458
  * BorrowKit, and UnifiedBalanceKit.
8459
8459
  *
8460
- * When `true`, completed earn, swap, borrow, and unified balance operations
8461
- * will not POST analytics events. This does not disable error reporting; use
8460
+ * When `true`, completed bridge, earn, swap, borrow, and unified balance
8461
+ * operations will not POST analytics events. This does not disable error reporting; use
8462
8462
  * {@link AppKitContext.disableErrorReporting} for that. Defaults to `false`.
8463
8463
  *
8464
8464
  * @defaultValue false
package/bridge.d.ts CHANGED
@@ -8454,11 +8454,11 @@ interface AppKitContext {
8454
8454
  */
8455
8455
  actions: Record<'bridge' | 'earn' | 'borrow', Record<string, ((payload: unknown) => void)[]>>;
8456
8456
  /**
8457
- * Disable success analytics for the underlying EarnKit, SwapKit,
8457
+ * Disable success analytics for the underlying BridgeKit, EarnKit, SwapKit,
8458
8458
  * BorrowKit, and UnifiedBalanceKit.
8459
8459
  *
8460
- * When `true`, completed earn, swap, borrow, and unified balance operations
8461
- * will not POST analytics events. This does not disable error reporting; use
8460
+ * When `true`, completed bridge, earn, swap, borrow, and unified balance
8461
+ * operations will not POST analytics events. This does not disable error reporting; use
8462
8462
  * {@link AppKitContext.disableErrorReporting} for that. Defaults to `false`.
8463
8463
  *
8464
8464
  * @defaultValue false