@circle-fin/app-kit 1.16.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 +79 -0
- package/borrow.cjs +150 -32
- package/borrow.d.cts +38 -9
- package/borrow.d.mts +38 -9
- package/borrow.d.ts +38 -9
- package/borrow.mjs +150 -32
- package/bridge.cjs +454 -53
- package/bridge.d.cts +38 -9
- package/bridge.d.mts +38 -9
- package/bridge.d.ts +38 -9
- package/bridge.mjs +454 -53
- package/chains.cjs +10 -6
- package/chains.d.cts +1 -1
- package/chains.d.mts +1 -1
- package/chains.d.ts +1 -1
- package/chains.mjs +10 -6
- package/context.d.cts +38 -9
- package/context.d.mts +38 -9
- package/context.d.ts +38 -9
- package/earn.cjs +830 -43
- package/earn.d.cts +38 -9
- package/earn.d.mts +38 -9
- package/earn.d.ts +38 -9
- package/earn.mjs +830 -43
- package/estimateBridge.cjs +454 -53
- package/estimateBridge.d.cts +38 -9
- package/estimateBridge.d.mts +38 -9
- package/estimateBridge.d.ts +38 -9
- package/estimateBridge.mjs +454 -53
- package/estimateSwap.cjs +265 -45
- package/estimateSwap.d.cts +86 -9
- package/estimateSwap.d.mts +86 -9
- package/estimateSwap.d.ts +86 -9
- package/estimateSwap.mjs +265 -45
- package/index.cjs +1019 -73
- package/index.d.cts +373 -210
- package/index.d.mts +373 -210
- package/index.d.ts +373 -210
- package/index.mjs +1019 -73
- package/package.json +8 -8
- package/server.cjs +35 -9
- package/server.d.cts +29 -10
- package/server.d.mts +29 -10
- package/server.d.ts +29 -10
- package/server.mjs +35 -9
- package/swap.cjs +265 -45
- package/swap.d.cts +86 -9
- package/swap.d.mts +86 -9
- package/swap.d.ts +86 -9
- package/swap.mjs +265 -45
- package/unifiedBalance.cjs +139 -20
- package/unifiedBalance.mjs +139 -20
package/bridge.cjs
CHANGED
|
@@ -2522,22 +2522,73 @@ let activeRedactor = defaultMessageRedactor;
|
|
|
2522
2522
|
'0x9147d463': 'Final balance is less than the initial balance',
|
|
2523
2523
|
'0xf4b3b1bc': 'Native token transfer to the beneficiary failed'
|
|
2524
2524
|
};
|
|
2525
|
+
/**
|
|
2526
|
+
* Matches revert data: a 4-byte selector followed by whole ABI-encoded bytes.
|
|
2527
|
+
*/ const REVERT_DATA_PATTERN = /^0x[0-9a-f]{8}(?:[0-9a-f]{2})*$/i;
|
|
2528
|
+
/**
|
|
2529
|
+
* Returns the revert data held by one error in a `cause` chain.
|
|
2530
|
+
*
|
|
2531
|
+
* Browser wallets (EIP-1193) wrap the node's error, so the revert data sits
|
|
2532
|
+
* one level down as `data.data`. viem's `getContractError` reads it the same
|
|
2533
|
+
* way, then keeps it on `ContractFunctionRevertedError.raw` and drops the
|
|
2534
|
+
* node's error from the chain.
|
|
2535
|
+
*
|
|
2536
|
+
* @param link - One error in the `cause` chain
|
|
2537
|
+
* @returns The `raw` or `data` string, or undefined if there is none
|
|
2538
|
+
*/ function getRevertData(link) {
|
|
2539
|
+
if ('raw' in link && typeof link.raw === 'string' && REVERT_DATA_PATTERN.test(link.raw)) {
|
|
2540
|
+
return link.raw;
|
|
2541
|
+
}
|
|
2542
|
+
if (!('data' in link)) {
|
|
2543
|
+
return undefined;
|
|
2544
|
+
}
|
|
2545
|
+
const { data } = link;
|
|
2546
|
+
if (typeof data === 'string') {
|
|
2547
|
+
return data;
|
|
2548
|
+
}
|
|
2549
|
+
if (data !== null && typeof data === 'object' && 'data' in data && typeof data.data === 'string') {
|
|
2550
|
+
return data.data;
|
|
2551
|
+
}
|
|
2552
|
+
return undefined;
|
|
2553
|
+
}
|
|
2554
|
+
/**
|
|
2555
|
+
* Finds the first revert data on the error or in its `cause` chain that
|
|
2556
|
+
* `accept` takes.
|
|
2557
|
+
*
|
|
2558
|
+
* viem keeps the node's revert data on an inner `RpcRequestError`, not on
|
|
2559
|
+
* the error it throws. The `seen` set stops a self-referencing `cause` chain.
|
|
2560
|
+
*
|
|
2561
|
+
* @param error - The error object
|
|
2562
|
+
* @param accept - Returns true for the data shape the caller wants
|
|
2563
|
+
* @returns The data as written on the error, or undefined if not found
|
|
2564
|
+
*/ function findRevertData(error, accept) {
|
|
2565
|
+
const seen = new Set();
|
|
2566
|
+
let current = error;
|
|
2567
|
+
while(current !== null && typeof current === 'object' && !seen.has(current)){
|
|
2568
|
+
seen.add(current);
|
|
2569
|
+
const data = getRevertData(current);
|
|
2570
|
+
if (data !== undefined && accept(data)) {
|
|
2571
|
+
return data;
|
|
2572
|
+
}
|
|
2573
|
+
current = 'cause' in current ? current.cause : undefined;
|
|
2574
|
+
}
|
|
2575
|
+
return undefined;
|
|
2576
|
+
}
|
|
2525
2577
|
/**
|
|
2526
2578
|
* Attempts to extract an error selector from an error object or message.
|
|
2527
2579
|
*
|
|
2528
2580
|
* Checks multiple sources in priority order:
|
|
2529
|
-
* 1. `
|
|
2581
|
+
* 1. `raw` or `data` field (or nested `data.data`) on the error or anywhere
|
|
2582
|
+
* in its `cause` chain
|
|
2530
2583
|
* 2. Message pattern: "custom error 0x8baa579f"
|
|
2531
2584
|
*
|
|
2532
2585
|
* @param msg - The error message
|
|
2533
2586
|
* @param error - The error object (optional)
|
|
2534
2587
|
* @returns The 4 bytes selector , or undefined if not found
|
|
2535
2588
|
*/ function extractErrorSelector(msg, error) {
|
|
2536
|
-
|
|
2537
|
-
if (
|
|
2538
|
-
|
|
2539
|
-
return error.data.toLowerCase();
|
|
2540
|
-
}
|
|
2589
|
+
const data = findRevertData(error, (value)=>/^0x[0-9a-f]{8}$/i.test(value));
|
|
2590
|
+
if (data !== undefined) {
|
|
2591
|
+
return data.toLowerCase();
|
|
2541
2592
|
}
|
|
2542
2593
|
// Check for "custom error 0x8baa579f" in the message
|
|
2543
2594
|
const match = /custom error (0x[0-9a-f]{8})\b/i.exec(msg);
|
|
@@ -3810,6 +3861,8 @@ var SwapChain;
|
|
|
3810
3861
|
SwapChain["HyperEVM"] = "HyperEVM";
|
|
3811
3862
|
SwapChain["Monad"] = "Monad";
|
|
3812
3863
|
SwapChain["Arc"] = "Arc";
|
|
3864
|
+
SwapChain["Cronos"] = "Cronos";
|
|
3865
|
+
SwapChain["Morph"] = "Morph";
|
|
3813
3866
|
// Testnet chains with swap support
|
|
3814
3867
|
SwapChain["Arc_Testnet"] = "Arc_Testnet";
|
|
3815
3868
|
})(SwapChain || (SwapChain = {}));
|
|
@@ -4490,14 +4543,14 @@ var BorrowChain;
|
|
|
4490
4543
|
symbol: 'USDC',
|
|
4491
4544
|
// Arc uses native USDC with 18 decimals for gas payments (EVM standard).
|
|
4492
4545
|
// Note: The ERC-20 USDC contract at usdcAddress uses 6 decimals.
|
|
4493
|
-
// See: https://docs.arc.
|
|
4546
|
+
// See: https://docs.arc.io/arc/references/contract-addresses
|
|
4494
4547
|
decimals: 18
|
|
4495
4548
|
},
|
|
4496
4549
|
chainId: 5042002,
|
|
4497
4550
|
isTestnet: true,
|
|
4498
4551
|
explorerUrl: 'https://testnet.arcscan.app/tx/{hash}',
|
|
4499
4552
|
rpcEndpoints: [
|
|
4500
|
-
'https://rpc.testnet.arc.
|
|
4553
|
+
'https://rpc.testnet.arc.io'
|
|
4501
4554
|
],
|
|
4502
4555
|
eurcAddress: '0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a',
|
|
4503
4556
|
usdcAddress: '0x3600000000000000000000000000000000000000',
|
|
@@ -5142,7 +5195,8 @@ var BorrowChain;
|
|
|
5142
5195
|
}
|
|
5143
5196
|
},
|
|
5144
5197
|
kitContracts: {
|
|
5145
|
-
bridge: BRIDGE_CONTRACT_EVM_MAINNET
|
|
5198
|
+
bridge: BRIDGE_CONTRACT_EVM_MAINNET,
|
|
5199
|
+
adapter: ADAPTER_CONTRACT_EVM_MAINNET
|
|
5146
5200
|
}
|
|
5147
5201
|
});
|
|
5148
5202
|
|
|
@@ -6011,7 +6065,8 @@ var BorrowChain;
|
|
|
6011
6065
|
}
|
|
6012
6066
|
},
|
|
6013
6067
|
kitContracts: {
|
|
6014
|
-
bridge: BRIDGE_CONTRACT_EVM_MAINNET
|
|
6068
|
+
bridge: BRIDGE_CONTRACT_EVM_MAINNET,
|
|
6069
|
+
adapter: ADAPTER_CONTRACT_EVM_MAINNET
|
|
6015
6070
|
}
|
|
6016
6071
|
});
|
|
6017
6072
|
|
|
@@ -8309,8 +8364,8 @@ var Chains = {
|
|
|
8309
8364
|
* Zod schema for validating swap-specific chain identifiers.
|
|
8310
8365
|
*
|
|
8311
8366
|
* Validates chains based on:
|
|
8312
|
-
* -
|
|
8313
|
-
* - Mainnet
|
|
8367
|
+
* - Membership in the SwapChain enum
|
|
8368
|
+
* - Mainnet or explicitly allowlisted testnet
|
|
8314
8369
|
* - At least one supported token available
|
|
8315
8370
|
*
|
|
8316
8371
|
*/ const swapChainIdentifierSchema = zod.z.union([
|
|
@@ -8789,7 +8844,7 @@ const swapTokenEnumSchema = zod.z.enum([
|
|
|
8789
8844
|
*
|
|
8790
8845
|
* A chain supports swaps if ALL conditions are met:
|
|
8791
8846
|
* 1. Is a member of the {@link SwapChain} enum
|
|
8792
|
-
* 2. Has
|
|
8847
|
+
* 2. Has an Adapter contract configured directly or through CCTP v2
|
|
8793
8848
|
*
|
|
8794
8849
|
* Testnets are allowed only when explicitly listed in the
|
|
8795
8850
|
* {@link SwapChain} enum (e.g., Arc_Testnet).
|
|
@@ -8810,14 +8865,14 @@ const swapTokenEnumSchema = zod.z.enum([
|
|
|
8810
8865
|
* @remarks
|
|
8811
8866
|
* Chains automatically become swap-enabled when:
|
|
8812
8867
|
* - Added to the {@link SwapChain} enum
|
|
8813
|
-
* - Adapter contract is deployed
|
|
8868
|
+
* - An Adapter contract is deployed and configured
|
|
8814
8869
|
*
|
|
8815
8870
|
* No code changes needed when new chains are added!
|
|
8816
8871
|
*/ function isSwapSupportedChain(chain) {
|
|
8817
8872
|
if (!(chain.chain in SwapChain)) {
|
|
8818
8873
|
return false;
|
|
8819
8874
|
}
|
|
8820
|
-
if (!isCCTPV2Supported(chain)) {
|
|
8875
|
+
if (!isCCTPV2Supported(chain) && !hasCustomContractSupport(chain, 'adapter')) {
|
|
8821
8876
|
return false;
|
|
8822
8877
|
}
|
|
8823
8878
|
return true;
|
|
@@ -8828,7 +8883,7 @@ const swapTokenEnumSchema = zod.z.enum([
|
|
|
8828
8883
|
*
|
|
8829
8884
|
* Dynamically filter chain definitions to include only those that:
|
|
8830
8885
|
* - Are members of the {@link SwapChain} enum
|
|
8831
|
-
* - Have
|
|
8886
|
+
* - Have an Adapter contract configured directly or through CCTP v2
|
|
8832
8887
|
*
|
|
8833
8888
|
* This function is pure and accepts chains as parameter to avoid
|
|
8834
8889
|
* circular dependencies.
|
|
@@ -10262,11 +10317,13 @@ function parseOrThrow(value, schema, context) {
|
|
|
10262
10317
|
[Blockchain.Arbitrum]: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9',
|
|
10263
10318
|
[Blockchain.Avalanche]: '0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7',
|
|
10264
10319
|
[Blockchain.Celo]: '0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e',
|
|
10320
|
+
[Blockchain.Cronos]: '0x66e428c3f67a68878562e79A0234c1F83c208770',
|
|
10265
10321
|
[Blockchain.Ethereum]: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
|
|
10266
10322
|
[Blockchain.HyperEVM]: '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb',
|
|
10267
10323
|
[Blockchain.Ink]: '0x0200C29006150606B650577BBE7B6248F58470c1',
|
|
10268
10324
|
[Blockchain.Linea]: '0xA219439258ca9da29E9Cc4cE5596924745e12B93',
|
|
10269
10325
|
[Blockchain.Monad]: '0xe7cd86e13AC4309349F30B3435a9d337750fC82D',
|
|
10326
|
+
[Blockchain.Morph]: '0xe7cd86e13AC4309349F30B3435a9d337750fC82D',
|
|
10270
10327
|
[Blockchain.NEAR]: 'usdt.tether-token.near',
|
|
10271
10328
|
[Blockchain.Optimism]: '0x94b008aA00579c1307B0EF2c499aD98a8ce58e58',
|
|
10272
10329
|
[Blockchain.Polkadot_Asset_Hub]: '1984',
|
|
@@ -10325,6 +10382,7 @@ function parseOrThrow(value, schema, context) {
|
|
|
10325
10382
|
[Blockchain.Arbitrum]: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1',
|
|
10326
10383
|
[Blockchain.Avalanche]: '0xd586E7F844cEa2F87f50152665BCbc2C279D8d70',
|
|
10327
10384
|
[Blockchain.Base]: '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb',
|
|
10385
|
+
[Blockchain.Cronos]: '0xF2001B145b43032AAF5Ee2884e456CCd805F677D',
|
|
10328
10386
|
[Blockchain.Ethereum]: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
|
|
10329
10387
|
[Blockchain.Linea]: '0x4AF15ec2A0BD43Db75dd04E62FAA3B8EF36b00d5',
|
|
10330
10388
|
[Blockchain.Optimism]: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1',
|
|
@@ -10387,7 +10445,9 @@ function parseOrThrow(value, schema, context) {
|
|
|
10387
10445
|
[Blockchain.Arbitrum]: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1',
|
|
10388
10446
|
[Blockchain.Avalanche]: '0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB',
|
|
10389
10447
|
[Blockchain.Base]: '0x4200000000000000000000000000000000000006',
|
|
10448
|
+
[Blockchain.Cronos]: '0xe44Fd7fCb2b1581822D0c862B68222998a0c299a',
|
|
10390
10449
|
[Blockchain.Ethereum]: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
|
|
10450
|
+
[Blockchain.Morph]: '0x5300000000000000000000000000000000000011',
|
|
10391
10451
|
[Blockchain.Optimism]: '0x4200000000000000000000000000000000000006',
|
|
10392
10452
|
[Blockchain.Polygon]: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619',
|
|
10393
10453
|
[Blockchain.Solana]: '7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs'
|
|
@@ -10406,6 +10466,7 @@ function parseOrThrow(value, schema, context) {
|
|
|
10406
10466
|
locators: {
|
|
10407
10467
|
[Blockchain.Ethereum]: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599',
|
|
10408
10468
|
[Blockchain.Arbitrum]: '0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f',
|
|
10469
|
+
[Blockchain.Cronos]: '0x062E66477Faf219F25D27dCED647BF57C3107d52',
|
|
10409
10470
|
[Blockchain.Avalanche]: '0x50b7545627a5162F82A992c33b87aDc75187B218'
|
|
10410
10471
|
}
|
|
10411
10472
|
};
|
|
@@ -12126,6 +12187,39 @@ function resolveOptions(options) {
|
|
|
12126
12187
|
}
|
|
12127
12188
|
};
|
|
12128
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
|
+
}
|
|
12129
12223
|
/**
|
|
12130
12224
|
* Wrap an async operation with error telemetry.
|
|
12131
12225
|
*
|
|
@@ -12236,7 +12330,7 @@ function resolveOptions(options) {
|
|
|
12236
12330
|
}
|
|
12237
12331
|
|
|
12238
12332
|
var name$3 = "@circle-fin/bridge-kit";
|
|
12239
|
-
var version$4 = "1.
|
|
12333
|
+
var version$4 = "1.16.0";
|
|
12240
12334
|
var pkg$4 = {
|
|
12241
12335
|
name: name$3,
|
|
12242
12336
|
version: version$4};
|
|
@@ -13497,6 +13591,53 @@ const EURC_MAINNET_TOKEN_ID = '0x6ca9e29fa53becc29becaf4a90b9ca7a995ad4d2234880d
|
|
|
13497
13591
|
}
|
|
13498
13592
|
};
|
|
13499
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
|
+
|
|
13500
13641
|
/**
|
|
13501
13642
|
* Default clock implementation.
|
|
13502
13643
|
*
|
|
@@ -14801,7 +14942,11 @@ function createNoopLogger() {
|
|
|
14801
14942
|
tokenId: bytes32Hex,
|
|
14802
14943
|
domainId: nonNegativeInteger,
|
|
14803
14944
|
tokenAddress: zod.z.string(),
|
|
14804
|
-
tokenManagerAddress: zod.z.string()
|
|
14945
|
+
tokenManagerAddress: zod.z.string(),
|
|
14946
|
+
// Operator-controlled per-chain kill switch (CCTPE-3979). Optional for
|
|
14947
|
+
// back-compat with older IRIS versions that do not surface it. Downstream
|
|
14948
|
+
// consumers in `findCCTPXDeployment` treat a missing value as `true`.
|
|
14949
|
+
enabled: zod.z.boolean().optional()
|
|
14805
14950
|
});
|
|
14806
14951
|
/**
|
|
14807
14952
|
* Schema for one token entry in the token registry response.
|
|
@@ -15285,17 +15430,23 @@ function createNoopLogger() {
|
|
|
15285
15430
|
/**
|
|
15286
15431
|
* Find a token's deployment on the given CCTP domain.
|
|
15287
15432
|
*
|
|
15433
|
+
* A deployment row with `enabled === false` is treated as missing: an IRIS
|
|
15434
|
+
* operator has flipped the per-chain kill switch (CCTPE-3979), so the SDK must
|
|
15435
|
+
* not route through it even though the row still exists in the registry. A
|
|
15436
|
+
* missing or `true` `enabled` value remains routable — the field is optional on
|
|
15437
|
+
* older IRIS versions and absence is read as "allowed".
|
|
15438
|
+
*
|
|
15288
15439
|
* @param token - The registry token whose deployments are searched.
|
|
15289
15440
|
* @param domain - The CCTP domain id to match.
|
|
15290
15441
|
* @returns The matching {@link CCTPXTokenDeployment}, or `undefined` when the
|
|
15291
|
-
* token has no deployment on that domain.
|
|
15442
|
+
* token has no deployment on that domain or the deployment is disabled.
|
|
15292
15443
|
*
|
|
15293
15444
|
* @example
|
|
15294
15445
|
* ```typescript
|
|
15295
15446
|
* const deployment = findCCTPXDeployment(token, 0)
|
|
15296
15447
|
* ```
|
|
15297
15448
|
*/ function findCCTPXDeployment(token, domain) {
|
|
15298
|
-
return token.deployments.find((deployment)=>deployment.domainId === domain);
|
|
15449
|
+
return token.deployments.find((deployment)=>deployment.domainId === domain && deployment.enabled !== false);
|
|
15299
15450
|
}
|
|
15300
15451
|
|
|
15301
15452
|
/**
|
|
@@ -15397,6 +15548,24 @@ function createNoopLogger() {
|
|
|
15397
15548
|
}
|
|
15398
15549
|
}
|
|
15399
15550
|
})
|
|
15551
|
+
],
|
|
15552
|
+
// The token is not deployed on one of the route chains, or an operator has
|
|
15553
|
+
// flipped the per-chain `enabled` kill switch on the IRIS deployment row.
|
|
15554
|
+
// Either way the route is permanently unavailable until the operator intervenes;
|
|
15555
|
+
// a retry at the same source/destination will keep returning this error.
|
|
15556
|
+
[
|
|
15557
|
+
'TOKEN_NOT_SUPPORTED_ON_ROUTE',
|
|
15558
|
+
({ sourceDomain, destinationDomain })=>new KitError({
|
|
15559
|
+
...InputError.UNSUPPORTED_ROUTE,
|
|
15560
|
+
recoverability: 'FATAL',
|
|
15561
|
+
message: 'CCTPx fee quote rejected the route: the token is not supported on ' + 'the source or destination chain (missing deployment or operator-disabled).',
|
|
15562
|
+
cause: {
|
|
15563
|
+
trace: {
|
|
15564
|
+
sourceDomain,
|
|
15565
|
+
destinationDomain
|
|
15566
|
+
}
|
|
15567
|
+
}
|
|
15568
|
+
})
|
|
15400
15569
|
]
|
|
15401
15570
|
]);
|
|
15402
15571
|
/**
|
|
@@ -20653,6 +20822,24 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
|
|
|
20653
20822
|
}
|
|
20654
20823
|
};
|
|
20655
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';
|
|
20656
20843
|
/**
|
|
20657
20844
|
* Build the forwarding `hookData` for a forwarded (Orbit-relayed) CCTP v2 burn,
|
|
20658
20845
|
* tailored to the destination chain.
|
|
@@ -21003,10 +21190,12 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
|
|
|
21003
21190
|
* @param sourceDomain - The source domain
|
|
21004
21191
|
* @param destinationDomain - The destination domain
|
|
21005
21192
|
* @param isTestnet - Whether the request is for a testnet chain
|
|
21193
|
+
* @param includeRecipientSetup - Whether the quote includes recipient account setup rent
|
|
21006
21194
|
* @returns The complete API URL with forward=true query parameter
|
|
21007
|
-
*/ function buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet) {
|
|
21195
|
+
*/ function buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet, includeRecipientSetup) {
|
|
21008
21196
|
const baseUrl = isTestnet ? IRIS_API_SANDBOX_BASE_URL$1 : IRIS_API_BASE_URL$1;
|
|
21009
|
-
|
|
21197
|
+
const recipientSetupQuery = includeRecipientSetup ? '&includeRecipientSetup=true' : '';
|
|
21198
|
+
return `${baseUrl}/v2/burn/USDC/fees/${sourceDomain.toString()}/${destinationDomain.toString()}?forward=true${recipientSetupQuery}`;
|
|
21010
21199
|
}
|
|
21011
21200
|
/**
|
|
21012
21201
|
* Fetches the forwarding fee for a USDC transfer operation with retry and timeout handling.
|
|
@@ -21023,6 +21212,10 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
|
|
|
21023
21212
|
*
|
|
21024
21213
|
* The high fee tier is always used to provide buffer for destination gas fluctuations.
|
|
21025
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
|
+
*
|
|
21026
21219
|
* Implements timeout and retry logic to handle network issues and temporary API failures.
|
|
21027
21220
|
* Each HTTP request is given a maximum of 2 seconds before it is aborted.
|
|
21028
21221
|
* We retry up to 10 times, waiting 200ms between attempts.
|
|
@@ -21031,6 +21224,8 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
|
|
|
21031
21224
|
* @param destinationDomain - The destination domain
|
|
21032
21225
|
* @param isTestnet - Whether the request is for a testnet chain
|
|
21033
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`.
|
|
21034
21229
|
* @returns The high-tier forwarding fee in USDC minor units (6 decimals)
|
|
21035
21230
|
* @throws Error if the input domains are invalid, the API request fails, returns invalid data, or network errors occur
|
|
21036
21231
|
*
|
|
@@ -21042,8 +21237,11 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
|
|
|
21042
21237
|
*
|
|
21043
21238
|
* // SLOW transfer - use 2000ms finality threshold
|
|
21044
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)
|
|
21045
21243
|
* ```
|
|
21046
|
-
*/ async function fetchForwardingFee(sourceDomain, destinationDomain, isTestnet, finalityThreshold) {
|
|
21244
|
+
*/ async function fetchForwardingFee(sourceDomain, destinationDomain, isTestnet, finalityThreshold, includeRecipientSetup = false) {
|
|
21047
21245
|
// Validate source domain
|
|
21048
21246
|
if (!Number.isInteger(sourceDomain) || sourceDomain < 0) {
|
|
21049
21247
|
throw new KitError({
|
|
@@ -21071,7 +21269,7 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
|
|
|
21071
21269
|
});
|
|
21072
21270
|
}
|
|
21073
21271
|
// Fetch the fee tiers from the API with forward=true
|
|
21074
|
-
const url = buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet);
|
|
21272
|
+
const url = buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet, includeRecipientSetup);
|
|
21075
21273
|
const response = await pollApiGet(url, isForwardingFeeResponse, DEFAULT_CONFIG$1);
|
|
21076
21274
|
// Validate that we have at least one fee tier
|
|
21077
21275
|
if (response.length === 0) {
|
|
@@ -23407,7 +23605,7 @@ const mockAttestationMessage = {
|
|
|
23407
23605
|
return step;
|
|
23408
23606
|
}
|
|
23409
23607
|
|
|
23410
|
-
var version$3 = "1.14.
|
|
23608
|
+
var version$3 = "1.14.3";
|
|
23411
23609
|
var pkg$3 = {
|
|
23412
23610
|
version: version$3};
|
|
23413
23611
|
|
|
@@ -24326,9 +24524,34 @@ function assertCCTPV2Config(config) {
|
|
|
24326
24524
|
tokenAddress: source.chain.usdcAddress,
|
|
24327
24525
|
operationContext: sourceOperationContext
|
|
24328
24526
|
});
|
|
24527
|
+
await this.assertAmountCoversRecipientSetupFee(params);
|
|
24329
24528
|
return bridge$1(params, this);
|
|
24330
24529
|
}
|
|
24331
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
|
+
/**
|
|
24332
24555
|
* Retry a failed or incomplete CCTP v2 bridge operation.
|
|
24333
24556
|
*
|
|
24334
24557
|
* Analyzes the bridge result to determine where to continue and executes
|
|
@@ -25045,6 +25268,9 @@ function assertCCTPV2Config(config) {
|
|
|
25045
25268
|
* | FAST | true | No | maxFee = calculatedBurnFee + forwardingFee |
|
|
25046
25269
|
* | FAST | true | Yes | maxFee = config.maxFee |
|
|
25047
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
|
+
*
|
|
25048
25274
|
* @param params - The bridge parameters object containing:
|
|
25049
25275
|
* - `source`: The source wallet context with chain definition and adapter
|
|
25050
25276
|
* - `destination`: The destination wallet context with chain definition and adapter
|
|
@@ -25083,6 +25309,7 @@ function assertCCTPV2Config(config) {
|
|
|
25083
25309
|
}
|
|
25084
25310
|
// Get the min finality threshold based on the transfer speed
|
|
25085
25311
|
const minFinalityThreshold = CCTPv2MinFinalityThreshold[transferSpeed];
|
|
25312
|
+
const includeRecipientSetup = requiresRecipientSetup(destination.chain.type);
|
|
25086
25313
|
// SLOW transfer without forwarder: no fee
|
|
25087
25314
|
if (transferSpeed === TransferSpeed.SLOW && !useForwarder) {
|
|
25088
25315
|
return {
|
|
@@ -25092,7 +25319,7 @@ function assertCCTPV2Config(config) {
|
|
|
25092
25319
|
}
|
|
25093
25320
|
// SLOW transfer with forwarder: only forwarding fee
|
|
25094
25321
|
if (transferSpeed === TransferSpeed.SLOW && useForwarder) {
|
|
25095
|
-
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);
|
|
25096
25323
|
return {
|
|
25097
25324
|
providerFee: 0n,
|
|
25098
25325
|
forwarderFee
|
|
@@ -25102,7 +25329,7 @@ function assertCCTPV2Config(config) {
|
|
|
25102
25329
|
// Fetch fees in parallel when forwarder is enabled
|
|
25103
25330
|
const [scaledBps, forwarderFee] = await Promise.all([
|
|
25104
25331
|
fetchUsdcFastBurnFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet),
|
|
25105
|
-
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)
|
|
25106
25333
|
]);
|
|
25107
25334
|
// Calculate fee proportional to the transfer amount
|
|
25108
25335
|
const amountInMinorUnits = BigInt(amount);
|
|
@@ -25652,6 +25879,21 @@ function assertCCTPV2Config(config) {
|
|
|
25652
25879
|
'bridge_forward'
|
|
25653
25880
|
]
|
|
25654
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
|
+
];
|
|
25655
25897
|
|
|
25656
25898
|
/**
|
|
25657
25899
|
* Base URL for Circle's Quote API (hosted in Iris) on mainnet/production.
|
|
@@ -26709,6 +26951,85 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
26709
26951
|
}
|
|
26710
26952
|
return undefined;
|
|
26711
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
|
+
}
|
|
26712
27033
|
/**
|
|
26713
27034
|
* BridgeKit caller component for retry and estimate operations.
|
|
26714
27035
|
*/ const BRIDGE_KIT_CALLER = {
|
|
@@ -26839,6 +27160,10 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
26839
27160
|
/** Whether error telemetry is disabled. */ disableErrorReporting;
|
|
26840
27161
|
/** Per-kit telemetry identity for shared helpers. */ telemetryConfig;
|
|
26841
27162
|
/**
|
|
27163
|
+
* Per-kit telemetry identity for success events. Gated by `disableAnalytics`
|
|
27164
|
+
* independently of `disableErrorReporting`.
|
|
27165
|
+
*/ analyticsTelemetryConfig;
|
|
27166
|
+
/**
|
|
26842
27167
|
* Create a new BridgeKit instance.
|
|
26843
27168
|
*
|
|
26844
27169
|
* @param config - The configuration containing the CCTPv2 provider
|
|
@@ -26865,6 +27190,11 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
26865
27190
|
sdkVersion: pkg$4.version,
|
|
26866
27191
|
disabled: this.disableErrorReporting
|
|
26867
27192
|
};
|
|
27193
|
+
this.analyticsTelemetryConfig = {
|
|
27194
|
+
sdkName: SDK_NAME,
|
|
27195
|
+
sdkVersion: pkg$4.version,
|
|
27196
|
+
disabled: config.disableAnalytics === true
|
|
27197
|
+
};
|
|
26868
27198
|
for (const provider of this.providers){
|
|
26869
27199
|
provider.registerDispatcher(this.actionDispatcher);
|
|
26870
27200
|
}
|
|
@@ -26878,7 +27208,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
26878
27208
|
this.actionDispatcher.off(actionOrWildCard, handler);
|
|
26879
27209
|
}
|
|
26880
27210
|
async bridge(params) {
|
|
26881
|
-
|
|
27211
|
+
const bridgeResult = await withErrorTelemetry(async ()=>{
|
|
26882
27212
|
// First validate the parameters
|
|
26883
27213
|
assertBridgeParams(params, bridgeParamsWithChainIdentifierSchema);
|
|
26884
27214
|
// Then resolve chain definitions (includes adapter chain support validation)
|
|
@@ -26915,7 +27245,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
26915
27245
|
emitResultStepErrorTelemetry(failedStep, BRIDGE_STEP_EVENT_MAP, BRIDGE_EVENT_TYPES.BRIDGE, this.telemetryConfig, {
|
|
26916
27246
|
sourceChain: resolveChainName(params.from.chain),
|
|
26917
27247
|
destinationChain: resolveChainName(params.to.chain),
|
|
26918
|
-
tokenIn:
|
|
27248
|
+
tokenIn: toTelemetryToken(result.token, result.source.chain),
|
|
26919
27249
|
...txHash != null && {
|
|
26920
27250
|
txHash
|
|
26921
27251
|
}
|
|
@@ -26927,6 +27257,8 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
26927
27257
|
destinationChain: resolveChainName(params.to.chain),
|
|
26928
27258
|
tokenIn: params.token
|
|
26929
27259
|
});
|
|
27260
|
+
emitBridgeSuccessTelemetry(bridgeResult, this.analyticsTelemetryConfig);
|
|
27261
|
+
return bridgeResult;
|
|
26930
27262
|
}
|
|
26931
27263
|
/**
|
|
26932
27264
|
* Retry a failed or incomplete cross-chain USDC bridge operation.
|
|
@@ -26997,7 +27329,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
26997
27329
|
* )
|
|
26998
27330
|
* ```
|
|
26999
27331
|
*/ async retry(result, context, invocationMeta) {
|
|
27000
|
-
|
|
27332
|
+
const retriedResult = await withErrorTelemetry(async ()=>{
|
|
27001
27333
|
// Cast the providers list to the wide view here. The tuple
|
|
27002
27334
|
// type on `this.providers` retains concrete provider types
|
|
27003
27335
|
// (CCTPv2 narrows `TToken` to `'USDC'`); calling `.retry`
|
|
@@ -27025,7 +27357,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
27025
27357
|
emitResultStepErrorTelemetry(failedStep, BRIDGE_STEP_EVENT_MAP, BRIDGE_EVENT_TYPES.RETRY, this.telemetryConfig, {
|
|
27026
27358
|
sourceChain: result.source.chain.chain,
|
|
27027
27359
|
destinationChain: result.destination.chain.chain,
|
|
27028
|
-
tokenIn: result.token,
|
|
27360
|
+
tokenIn: toTelemetryToken(result.token, result.source.chain),
|
|
27029
27361
|
...txHash != null && {
|
|
27030
27362
|
txHash
|
|
27031
27363
|
}
|
|
@@ -27039,8 +27371,16 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
27039
27371
|
}, BRIDGE_EVENT_TYPES.RETRY, this.telemetryConfig, {
|
|
27040
27372
|
sourceChain: result.source.chain.chain,
|
|
27041
27373
|
destinationChain: result.destination.chain.chain,
|
|
27042
|
-
tokenIn: result.token
|
|
27374
|
+
tokenIn: toTelemetryToken(result.token, result.source.chain)
|
|
27043
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;
|
|
27044
27384
|
}
|
|
27045
27385
|
async estimate(params) {
|
|
27046
27386
|
return withErrorTelemetry(async ()=>{
|
|
@@ -27636,6 +27976,9 @@ registerKit(`${pkg$4.name}/${pkg$4.version}`);
|
|
|
27636
27976
|
...context.disableErrorReporting != null && {
|
|
27637
27977
|
disableErrorReporting: context.disableErrorReporting
|
|
27638
27978
|
},
|
|
27979
|
+
...context.disableAnalytics != null && {
|
|
27980
|
+
disableAnalytics: context.disableAnalytics
|
|
27981
|
+
},
|
|
27639
27982
|
...context.headers != null && {
|
|
27640
27983
|
headers: context.headers
|
|
27641
27984
|
}
|
|
@@ -27658,7 +28001,7 @@ registerKit(`${pkg$4.name}/${pkg$4.version}`);
|
|
|
27658
28001
|
};
|
|
27659
28002
|
|
|
27660
28003
|
var name$2 = "@circle-fin/swap-kit";
|
|
27661
|
-
var version$2 = "1.
|
|
28004
|
+
var version$2 = "1.8.1";
|
|
27662
28005
|
var pkg$2 = {
|
|
27663
28006
|
name: name$2,
|
|
27664
28007
|
version: version$2};
|
|
@@ -28000,6 +28343,64 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
|
|
|
28000
28343
|
}, {
|
|
28001
28344
|
message: 'fee amount must be non-negative (>= 0)'
|
|
28002
28345
|
});
|
|
28346
|
+
/**
|
|
28347
|
+
* Parses a display-only field leniently: a value `schema` rejects is replaced
|
|
28348
|
+
* with `fallback` instead of failing the response that carries it.
|
|
28349
|
+
* Implemented with `preprocess` rather than Zod's `.catch()` because static
|
|
28350
|
+
* analysis misreads `.catch` on the schema chain as an unhandled Promise
|
|
28351
|
+
* (S7785).
|
|
28352
|
+
*/ const withFallback = (schema, fallback)=>zod.z.preprocess((value)=>schema.safeParse(value).success ? value : fallback, schema);
|
|
28353
|
+
const swapRouteTokenSchema = zod.z.object({
|
|
28354
|
+
symbol: zod.z.string(),
|
|
28355
|
+
address: zod.z.string(),
|
|
28356
|
+
decimals: zod.z.number()
|
|
28357
|
+
});
|
|
28358
|
+
const swapRouteMetadataSchema = zod.z.record(zod.z.unknown()).optional();
|
|
28359
|
+
const swapRouteStepSchema = zod.z.object({
|
|
28360
|
+
type: zod.z.string(),
|
|
28361
|
+
tool: zod.z.string(),
|
|
28362
|
+
toolName: zod.z.string(),
|
|
28363
|
+
fromToken: swapRouteTokenSchema,
|
|
28364
|
+
toToken: swapRouteTokenSchema,
|
|
28365
|
+
estimate: zod.z.object({
|
|
28366
|
+
fromAmount: zod.z.string(),
|
|
28367
|
+
toAmount: zod.z.string(),
|
|
28368
|
+
gasCostUSD: zod.z.string().optional()
|
|
28369
|
+
}),
|
|
28370
|
+
metadata: swapRouteMetadataSchema
|
|
28371
|
+
});
|
|
28372
|
+
/**
|
|
28373
|
+
* Strict schema for a `SwapRoute`. Module-private: service responses
|
|
28374
|
+
* parse routes leniently through {@link responseSwapRouteSchema}.
|
|
28375
|
+
*/ const swapRouteSchema = zod.z.object({
|
|
28376
|
+
provider: zod.z.string().min(1, 'provider must be a non-empty string'),
|
|
28377
|
+
steps: zod.z.array(swapRouteStepSchema),
|
|
28378
|
+
metadata: swapRouteMetadataSchema
|
|
28379
|
+
});
|
|
28380
|
+
/**
|
|
28381
|
+
* Route details are display-only, so service responses parse them leniently:
|
|
28382
|
+
* steps or metadata in a shape the SDK does not know are dropped rather than
|
|
28383
|
+
* failing the quote or swap they describe. Steps are all-or-nothing: if any
|
|
28384
|
+
* step is malformed, `steps` is empty, so a route never silently loses a hop.
|
|
28385
|
+
*/ const responseSwapRouteSchema = swapRouteSchema.extend({
|
|
28386
|
+
steps: withFallback(swapRouteSchema.shape.steps, []),
|
|
28387
|
+
metadata: withFallback(swapRouteMetadataSchema, undefined)
|
|
28388
|
+
});
|
|
28389
|
+
const createSwapFeeItemSchema = zod.z.object({
|
|
28390
|
+
token: zod.z.string({
|
|
28391
|
+
required_error: 'fee token is required',
|
|
28392
|
+
invalid_type_error: 'fee token must be a string'
|
|
28393
|
+
}).min(1, 'fee token must be a non-empty string'),
|
|
28394
|
+
amount: feeAmountSchema,
|
|
28395
|
+
decimals: zod.z.number().int('fee token decimals must be an integer').nonnegative('fee token decimals must be a non-negative integer').optional(),
|
|
28396
|
+
symbol: zod.z.string({
|
|
28397
|
+
invalid_type_error: 'fee token symbol must be a string'
|
|
28398
|
+
}).min(1, 'fee token symbol must be a non-empty string').optional(),
|
|
28399
|
+
// Descriptive metadata: a value the SDK cannot use is dropped rather than
|
|
28400
|
+
// failing the response that carries the fee.
|
|
28401
|
+
type: withFallback(zod.z.string().min(1).optional(), undefined),
|
|
28402
|
+
chain: withFallback(zod.z.string().min(1).optional(), undefined)
|
|
28403
|
+
});
|
|
28003
28404
|
/**
|
|
28004
28405
|
* Zod schema for validating API keys.
|
|
28005
28406
|
*
|
|
@@ -28085,10 +28486,7 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
|
|
|
28085
28486
|
/** Quote information with estimated amounts and route */ quote: zod.z.object({
|
|
28086
28487
|
/** Estimated output amount (base units) */ estimatedAmount: zod.z.string().min(1, 'estimatedAmount must be a non-empty string').regex(/^\d+$/, 'estimatedAmount must be a numeric string'),
|
|
28087
28488
|
/** Guaranteed minimum output amount (base units) */ minAmount: zod.z.string().min(1, 'minAmount must be a non-empty string').regex(/^\d+$/, 'minAmount must be a numeric string'),
|
|
28088
|
-
/** Route information from DEX aggregator */ route:
|
|
28089
|
-
provider: zod.z.string().min(1, 'provider must be a non-empty string'),
|
|
28090
|
-
steps: zod.z.array(zod.z.unknown())
|
|
28091
|
-
})
|
|
28489
|
+
/** Route information from DEX aggregator */ route: responseSwapRouteSchema
|
|
28092
28490
|
}),
|
|
28093
28491
|
/** Fee context indicating where fees should be collected */ feeContext: quoteFeeContextSchema
|
|
28094
28492
|
});
|
|
@@ -28304,19 +28702,6 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
|
|
|
28304
28702
|
}).min(1, 'toChain must be a non-empty string if provided').optional(),
|
|
28305
28703
|
apiKey: apiKeySchema.optional()
|
|
28306
28704
|
});
|
|
28307
|
-
/**
|
|
28308
|
-
* Zod schema for validating CreateSwapResponse payloads.
|
|
28309
|
-
*/ const createSwapFeeItemSchema = zod.z.object({
|
|
28310
|
-
token: zod.z.string({
|
|
28311
|
-
required_error: 'fee token is required',
|
|
28312
|
-
invalid_type_error: 'fee token must be a string'
|
|
28313
|
-
}).min(1, 'fee token must be a non-empty string'),
|
|
28314
|
-
amount: feeAmountSchema,
|
|
28315
|
-
decimals: zod.z.number().int('fee token decimals must be an integer').nonnegative('fee token decimals must be a non-negative integer').optional(),
|
|
28316
|
-
symbol: zod.z.string({
|
|
28317
|
-
invalid_type_error: 'fee token symbol must be a string'
|
|
28318
|
-
}).min(1, 'fee token symbol must be a non-empty string').optional()
|
|
28319
|
-
});
|
|
28320
28705
|
/**
|
|
28321
28706
|
* Developer fee item schema with basis field.
|
|
28322
28707
|
*/ const createSwapDeveloperFeeItemSchema = createSwapFeeItemSchema.extend({
|
|
@@ -28454,6 +28839,8 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
|
|
|
28454
28839
|
correlationId: zod.z.preprocess((value)=>zod.z.string().uuid().safeParse(value).success ? value : undefined, zod.z.string().optional()),
|
|
28455
28840
|
config: createSwapRequestBaseSchema.shape.config.optional(),
|
|
28456
28841
|
fees: createSwapFeesSchema.optional(),
|
|
28842
|
+
// A route the SDK cannot parse is dropped instead of failing the swap.
|
|
28843
|
+
route: withFallback(responseSwapRouteSchema.optional(), undefined),
|
|
28457
28844
|
transaction: createSwapTransactionSchema
|
|
28458
28845
|
});
|
|
28459
28846
|
|
|
@@ -29581,6 +29968,16 @@ createTokenRegistry();
|
|
|
29581
29968
|
name: 'USDC',
|
|
29582
29969
|
version: '2'
|
|
29583
29970
|
},
|
|
29971
|
+
Cronos: {
|
|
29972
|
+
chainId: Cronos.chainId,
|
|
29973
|
+
name: 'USDC',
|
|
29974
|
+
version: '2'
|
|
29975
|
+
},
|
|
29976
|
+
Morph: {
|
|
29977
|
+
chainId: Morph.chainId,
|
|
29978
|
+
name: 'USDC',
|
|
29979
|
+
version: '2'
|
|
29980
|
+
},
|
|
29584
29981
|
Arc_Testnet: {
|
|
29585
29982
|
chainId: ArcTestnet.chainId,
|
|
29586
29983
|
name: 'USDC',
|
|
@@ -29669,6 +30066,7 @@ const optionalSwapChainIdentifierField = swapChainIdentifierField.optional();
|
|
|
29669
30066
|
* - customFee: Optional fee configuration
|
|
29670
30067
|
* - apiKey: Optional credential string
|
|
29671
30068
|
* - kitKey: Optional credential string (deprecated alias for apiKey)
|
|
30069
|
+
* - batchTransactions: Optional boolean to opt out of atomic batching
|
|
29672
30070
|
*/ const swapConfigSchema = zod.z.object({
|
|
29673
30071
|
allowanceStrategy: allowanceStrategySchema.optional(),
|
|
29674
30072
|
slippageBps: zod.z.number().int().min(0).optional(),
|
|
@@ -29679,7 +30077,10 @@ const optionalSwapChainIdentifierField = swapChainIdentifierField.optional();
|
|
|
29679
30077
|
})(zod.z.string())).optional(),
|
|
29680
30078
|
customFee: swapCustomFeeSchema.optional(),
|
|
29681
30079
|
apiKey: zod.z.string().optional(),
|
|
29682
|
-
kitKey: zod.z.string().optional()
|
|
30080
|
+
kitKey: zod.z.string().optional(),
|
|
30081
|
+
batchTransactions: zod.z.boolean({
|
|
30082
|
+
invalid_type_error: 'batchTransactions must be a boolean'
|
|
30083
|
+
}).optional()
|
|
29683
30084
|
});
|
|
29684
30085
|
const swapDestinationSchema = zod.z.object({
|
|
29685
30086
|
chain: optionalSwapChainIdentifierField,
|
|
@@ -29872,7 +30273,7 @@ new Set(Object.values(Blockchain));
|
|
|
29872
30273
|
registerKit(`${pkg$2.name}/${pkg$2.version}`);
|
|
29873
30274
|
|
|
29874
30275
|
var name$1 = "@circle-fin/earn-kit";
|
|
29875
|
-
var version$1 = "1.
|
|
30276
|
+
var version$1 = "1.10.0";
|
|
29876
30277
|
var pkg$1 = {
|
|
29877
30278
|
name: name$1,
|
|
29878
30279
|
version: version$1};
|
|
@@ -31376,7 +31777,7 @@ registerKit(`${pkg$1.name}/${pkg$1.version}`);
|
|
|
31376
31777
|
};
|
|
31377
31778
|
|
|
31378
31779
|
var name = "@circle-fin/borrow-kit";
|
|
31379
|
-
var version = "1.
|
|
31780
|
+
var version = "1.1.1";
|
|
31380
31781
|
var pkg = {
|
|
31381
31782
|
name: name,
|
|
31382
31783
|
version: version};
|