@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/CHANGELOG.md +41 -0
- package/borrow.cjs +6 -6
- package/borrow.d.cts +3 -3
- package/borrow.d.mts +3 -3
- package/borrow.d.ts +3 -3
- package/borrow.mjs +6 -6
- package/bridge.cjs +272 -18
- package/bridge.d.cts +3 -3
- package/bridge.d.mts +3 -3
- package/bridge.d.ts +3 -3
- package/bridge.mjs +272 -18
- package/chains.cjs +2 -2
- package/chains.d.cts +1 -1
- package/chains.d.mts +1 -1
- package/chains.d.ts +1 -1
- package/chains.mjs +2 -2
- package/context.d.cts +3 -3
- package/context.d.mts +3 -3
- package/context.d.ts +3 -3
- package/earn.cjs +365 -14
- package/earn.d.cts +3 -3
- package/earn.d.mts +3 -3
- package/earn.d.ts +3 -3
- package/earn.mjs +365 -14
- package/estimateBridge.cjs +272 -18
- package/estimateBridge.d.cts +3 -3
- package/estimateBridge.d.mts +3 -3
- package/estimateBridge.d.ts +3 -3
- package/estimateBridge.mjs +272 -18
- package/estimateSwap.cjs +6 -6
- package/estimateSwap.d.cts +3 -3
- package/estimateSwap.d.mts +3 -3
- package/estimateSwap.d.ts +3 -3
- package/estimateSwap.mjs +6 -6
- package/index.cjs +558 -27
- package/index.d.cts +42 -8
- package/index.d.mts +42 -8
- package/index.d.ts +42 -8
- package/index.mjs +558 -27
- package/package.json +8 -8
- package/server.cjs +3 -3
- package/server.mjs +3 -3
- package/swap.cjs +6 -6
- package/swap.d.cts +3 -3
- package/swap.d.mts +3 -3
- package/swap.d.ts +3 -3
- package/swap.mjs +6 -6
- package/unifiedBalance.cjs +68 -10
- package/unifiedBalance.mjs +68 -10
package/estimateBridge.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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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(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
|
-
|
|
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:
|
|
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
|
-
|
|
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.
|
|
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.
|
|
30276
|
+
var version$1 = "1.10.0";
|
|
30023
30277
|
var pkg$1 = {
|
|
30024
30278
|
name: name$1,
|
|
30025
30279
|
version: version$1};
|
|
@@ -31459,7 +31713,7 @@ function hasCrossChainDepositQuoteShape(params) {
|
|
|
31459
31713
|
registerKit(`${pkg$1.name}/${pkg$1.version}`);
|
|
31460
31714
|
|
|
31461
31715
|
var name = "@circle-fin/borrow-kit";
|
|
31462
|
-
var version = "1.1.
|
|
31716
|
+
var version = "1.1.1";
|
|
31463
31717
|
var pkg = {
|
|
31464
31718
|
name: name,
|
|
31465
31719
|
version: version};
|
package/estimateBridge.d.cts
CHANGED
|
@@ -8477,11 +8477,11 @@ interface AppKitContext {
|
|
|
8477
8477
|
*/
|
|
8478
8478
|
actions: Record<'bridge' | 'earn' | 'borrow', Record<string, ((payload: unknown) => void)[]>>;
|
|
8479
8479
|
/**
|
|
8480
|
-
* Disable success analytics for the underlying EarnKit, SwapKit,
|
|
8480
|
+
* Disable success analytics for the underlying BridgeKit, EarnKit, SwapKit,
|
|
8481
8481
|
* BorrowKit, and UnifiedBalanceKit.
|
|
8482
8482
|
*
|
|
8483
|
-
* When `true`, completed earn, swap, borrow, and unified balance
|
|
8484
|
-
* will not POST analytics events. This does not disable error reporting; use
|
|
8483
|
+
* When `true`, completed bridge, earn, swap, borrow, and unified balance
|
|
8484
|
+
* operations will not POST analytics events. This does not disable error reporting; use
|
|
8485
8485
|
* {@link AppKitContext.disableErrorReporting} for that. Defaults to `false`.
|
|
8486
8486
|
*
|
|
8487
8487
|
* @defaultValue false
|
package/estimateBridge.d.mts
CHANGED
|
@@ -8477,11 +8477,11 @@ interface AppKitContext {
|
|
|
8477
8477
|
*/
|
|
8478
8478
|
actions: Record<'bridge' | 'earn' | 'borrow', Record<string, ((payload: unknown) => void)[]>>;
|
|
8479
8479
|
/**
|
|
8480
|
-
* Disable success analytics for the underlying EarnKit, SwapKit,
|
|
8480
|
+
* Disable success analytics for the underlying BridgeKit, EarnKit, SwapKit,
|
|
8481
8481
|
* BorrowKit, and UnifiedBalanceKit.
|
|
8482
8482
|
*
|
|
8483
|
-
* When `true`, completed earn, swap, borrow, and unified balance
|
|
8484
|
-
* will not POST analytics events. This does not disable error reporting; use
|
|
8483
|
+
* When `true`, completed bridge, earn, swap, borrow, and unified balance
|
|
8484
|
+
* operations will not POST analytics events. This does not disable error reporting; use
|
|
8485
8485
|
* {@link AppKitContext.disableErrorReporting} for that. Defaults to `false`.
|
|
8486
8486
|
*
|
|
8487
8487
|
* @defaultValue false
|
package/estimateBridge.d.ts
CHANGED
|
@@ -8477,11 +8477,11 @@ interface AppKitContext {
|
|
|
8477
8477
|
*/
|
|
8478
8478
|
actions: Record<'bridge' | 'earn' | 'borrow', Record<string, ((payload: unknown) => void)[]>>;
|
|
8479
8479
|
/**
|
|
8480
|
-
* Disable success analytics for the underlying EarnKit, SwapKit,
|
|
8480
|
+
* Disable success analytics for the underlying BridgeKit, EarnKit, SwapKit,
|
|
8481
8481
|
* BorrowKit, and UnifiedBalanceKit.
|
|
8482
8482
|
*
|
|
8483
|
-
* When `true`, completed earn, swap, borrow, and unified balance
|
|
8484
|
-
* will not POST analytics events. This does not disable error reporting; use
|
|
8483
|
+
* When `true`, completed bridge, earn, swap, borrow, and unified balance
|
|
8484
|
+
* operations will not POST analytics events. This does not disable error reporting; use
|
|
8485
8485
|
* {@link AppKitContext.disableErrorReporting} for that. Defaults to `false`.
|
|
8486
8486
|
*
|
|
8487
8487
|
* @defaultValue false
|