@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.mjs
CHANGED
|
@@ -2515,22 +2515,73 @@ let activeRedactor = defaultMessageRedactor;
|
|
|
2515
2515
|
'0x9147d463': 'Final balance is less than the initial balance',
|
|
2516
2516
|
'0xf4b3b1bc': 'Native token transfer to the beneficiary failed'
|
|
2517
2517
|
};
|
|
2518
|
+
/**
|
|
2519
|
+
* Matches revert data: a 4-byte selector followed by whole ABI-encoded bytes.
|
|
2520
|
+
*/ const REVERT_DATA_PATTERN = /^0x[0-9a-f]{8}(?:[0-9a-f]{2})*$/i;
|
|
2521
|
+
/**
|
|
2522
|
+
* Returns the revert data held by one error in a `cause` chain.
|
|
2523
|
+
*
|
|
2524
|
+
* Browser wallets (EIP-1193) wrap the node's error, so the revert data sits
|
|
2525
|
+
* one level down as `data.data`. viem's `getContractError` reads it the same
|
|
2526
|
+
* way, then keeps it on `ContractFunctionRevertedError.raw` and drops the
|
|
2527
|
+
* node's error from the chain.
|
|
2528
|
+
*
|
|
2529
|
+
* @param link - One error in the `cause` chain
|
|
2530
|
+
* @returns The `raw` or `data` string, or undefined if there is none
|
|
2531
|
+
*/ function getRevertData(link) {
|
|
2532
|
+
if ('raw' in link && typeof link.raw === 'string' && REVERT_DATA_PATTERN.test(link.raw)) {
|
|
2533
|
+
return link.raw;
|
|
2534
|
+
}
|
|
2535
|
+
if (!('data' in link)) {
|
|
2536
|
+
return undefined;
|
|
2537
|
+
}
|
|
2538
|
+
const { data } = link;
|
|
2539
|
+
if (typeof data === 'string') {
|
|
2540
|
+
return data;
|
|
2541
|
+
}
|
|
2542
|
+
if (data !== null && typeof data === 'object' && 'data' in data && typeof data.data === 'string') {
|
|
2543
|
+
return data.data;
|
|
2544
|
+
}
|
|
2545
|
+
return undefined;
|
|
2546
|
+
}
|
|
2547
|
+
/**
|
|
2548
|
+
* Finds the first revert data on the error or in its `cause` chain that
|
|
2549
|
+
* `accept` takes.
|
|
2550
|
+
*
|
|
2551
|
+
* viem keeps the node's revert data on an inner `RpcRequestError`, not on
|
|
2552
|
+
* the error it throws. The `seen` set stops a self-referencing `cause` chain.
|
|
2553
|
+
*
|
|
2554
|
+
* @param error - The error object
|
|
2555
|
+
* @param accept - Returns true for the data shape the caller wants
|
|
2556
|
+
* @returns The data as written on the error, or undefined if not found
|
|
2557
|
+
*/ function findRevertData(error, accept) {
|
|
2558
|
+
const seen = new Set();
|
|
2559
|
+
let current = error;
|
|
2560
|
+
while(current !== null && typeof current === 'object' && !seen.has(current)){
|
|
2561
|
+
seen.add(current);
|
|
2562
|
+
const data = getRevertData(current);
|
|
2563
|
+
if (data !== undefined && accept(data)) {
|
|
2564
|
+
return data;
|
|
2565
|
+
}
|
|
2566
|
+
current = 'cause' in current ? current.cause : undefined;
|
|
2567
|
+
}
|
|
2568
|
+
return undefined;
|
|
2569
|
+
}
|
|
2518
2570
|
/**
|
|
2519
2571
|
* Attempts to extract an error selector from an error object or message.
|
|
2520
2572
|
*
|
|
2521
2573
|
* Checks multiple sources in priority order:
|
|
2522
|
-
* 1. `
|
|
2574
|
+
* 1. `raw` or `data` field (or nested `data.data`) on the error or anywhere
|
|
2575
|
+
* in its `cause` chain
|
|
2523
2576
|
* 2. Message pattern: "custom error 0x8baa579f"
|
|
2524
2577
|
*
|
|
2525
2578
|
* @param msg - The error message
|
|
2526
2579
|
* @param error - The error object (optional)
|
|
2527
2580
|
* @returns The 4 bytes selector , or undefined if not found
|
|
2528
2581
|
*/ function extractErrorSelector(msg, error) {
|
|
2529
|
-
|
|
2530
|
-
if (
|
|
2531
|
-
|
|
2532
|
-
return error.data.toLowerCase();
|
|
2533
|
-
}
|
|
2582
|
+
const data = findRevertData(error, (value)=>/^0x[0-9a-f]{8}$/i.test(value));
|
|
2583
|
+
if (data !== undefined) {
|
|
2584
|
+
return data.toLowerCase();
|
|
2534
2585
|
}
|
|
2535
2586
|
// Check for "custom error 0x8baa579f" in the message
|
|
2536
2587
|
const match = /custom error (0x[0-9a-f]{8})\b/i.exec(msg);
|
|
@@ -3803,6 +3854,8 @@ var SwapChain;
|
|
|
3803
3854
|
SwapChain["HyperEVM"] = "HyperEVM";
|
|
3804
3855
|
SwapChain["Monad"] = "Monad";
|
|
3805
3856
|
SwapChain["Arc"] = "Arc";
|
|
3857
|
+
SwapChain["Cronos"] = "Cronos";
|
|
3858
|
+
SwapChain["Morph"] = "Morph";
|
|
3806
3859
|
// Testnet chains with swap support
|
|
3807
3860
|
SwapChain["Arc_Testnet"] = "Arc_Testnet";
|
|
3808
3861
|
})(SwapChain || (SwapChain = {}));
|
|
@@ -4483,14 +4536,14 @@ var BorrowChain;
|
|
|
4483
4536
|
symbol: 'USDC',
|
|
4484
4537
|
// Arc uses native USDC with 18 decimals for gas payments (EVM standard).
|
|
4485
4538
|
// Note: The ERC-20 USDC contract at usdcAddress uses 6 decimals.
|
|
4486
|
-
// See: https://docs.arc.
|
|
4539
|
+
// See: https://docs.arc.io/arc/references/contract-addresses
|
|
4487
4540
|
decimals: 18
|
|
4488
4541
|
},
|
|
4489
4542
|
chainId: 5042002,
|
|
4490
4543
|
isTestnet: true,
|
|
4491
4544
|
explorerUrl: 'https://testnet.arcscan.app/tx/{hash}',
|
|
4492
4545
|
rpcEndpoints: [
|
|
4493
|
-
'https://rpc.testnet.arc.
|
|
4546
|
+
'https://rpc.testnet.arc.io'
|
|
4494
4547
|
],
|
|
4495
4548
|
eurcAddress: '0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a',
|
|
4496
4549
|
usdcAddress: '0x3600000000000000000000000000000000000000',
|
|
@@ -5135,7 +5188,8 @@ var BorrowChain;
|
|
|
5135
5188
|
}
|
|
5136
5189
|
},
|
|
5137
5190
|
kitContracts: {
|
|
5138
|
-
bridge: BRIDGE_CONTRACT_EVM_MAINNET
|
|
5191
|
+
bridge: BRIDGE_CONTRACT_EVM_MAINNET,
|
|
5192
|
+
adapter: ADAPTER_CONTRACT_EVM_MAINNET
|
|
5139
5193
|
}
|
|
5140
5194
|
});
|
|
5141
5195
|
|
|
@@ -6004,7 +6058,8 @@ var BorrowChain;
|
|
|
6004
6058
|
}
|
|
6005
6059
|
},
|
|
6006
6060
|
kitContracts: {
|
|
6007
|
-
bridge: BRIDGE_CONTRACT_EVM_MAINNET
|
|
6061
|
+
bridge: BRIDGE_CONTRACT_EVM_MAINNET,
|
|
6062
|
+
adapter: ADAPTER_CONTRACT_EVM_MAINNET
|
|
6008
6063
|
}
|
|
6009
6064
|
});
|
|
6010
6065
|
|
|
@@ -8302,8 +8357,8 @@ var Chains = /*#__PURE__*/Object.freeze({
|
|
|
8302
8357
|
* Zod schema for validating swap-specific chain identifiers.
|
|
8303
8358
|
*
|
|
8304
8359
|
* Validates chains based on:
|
|
8305
|
-
* -
|
|
8306
|
-
* - Mainnet
|
|
8360
|
+
* - Membership in the SwapChain enum
|
|
8361
|
+
* - Mainnet or explicitly allowlisted testnet
|
|
8307
8362
|
* - At least one supported token available
|
|
8308
8363
|
*
|
|
8309
8364
|
*/ const swapChainIdentifierSchema = z.union([
|
|
@@ -8782,7 +8837,7 @@ const swapTokenEnumSchema = z.enum([
|
|
|
8782
8837
|
*
|
|
8783
8838
|
* A chain supports swaps if ALL conditions are met:
|
|
8784
8839
|
* 1. Is a member of the {@link SwapChain} enum
|
|
8785
|
-
* 2. Has
|
|
8840
|
+
* 2. Has an Adapter contract configured directly or through CCTP v2
|
|
8786
8841
|
*
|
|
8787
8842
|
* Testnets are allowed only when explicitly listed in the
|
|
8788
8843
|
* {@link SwapChain} enum (e.g., Arc_Testnet).
|
|
@@ -8803,14 +8858,14 @@ const swapTokenEnumSchema = z.enum([
|
|
|
8803
8858
|
* @remarks
|
|
8804
8859
|
* Chains automatically become swap-enabled when:
|
|
8805
8860
|
* - Added to the {@link SwapChain} enum
|
|
8806
|
-
* - Adapter contract is deployed
|
|
8861
|
+
* - An Adapter contract is deployed and configured
|
|
8807
8862
|
*
|
|
8808
8863
|
* No code changes needed when new chains are added!
|
|
8809
8864
|
*/ function isSwapSupportedChain(chain) {
|
|
8810
8865
|
if (!(chain.chain in SwapChain)) {
|
|
8811
8866
|
return false;
|
|
8812
8867
|
}
|
|
8813
|
-
if (!isCCTPV2Supported(chain)) {
|
|
8868
|
+
if (!isCCTPV2Supported(chain) && !hasCustomContractSupport(chain, 'adapter')) {
|
|
8814
8869
|
return false;
|
|
8815
8870
|
}
|
|
8816
8871
|
return true;
|
|
@@ -8821,7 +8876,7 @@ const swapTokenEnumSchema = z.enum([
|
|
|
8821
8876
|
*
|
|
8822
8877
|
* Dynamically filter chain definitions to include only those that:
|
|
8823
8878
|
* - Are members of the {@link SwapChain} enum
|
|
8824
|
-
* - Have
|
|
8879
|
+
* - Have an Adapter contract configured directly or through CCTP v2
|
|
8825
8880
|
*
|
|
8826
8881
|
* This function is pure and accepts chains as parameter to avoid
|
|
8827
8882
|
* circular dependencies.
|
|
@@ -10255,11 +10310,13 @@ function parseOrThrow(value, schema, context) {
|
|
|
10255
10310
|
[Blockchain.Arbitrum]: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9',
|
|
10256
10311
|
[Blockchain.Avalanche]: '0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7',
|
|
10257
10312
|
[Blockchain.Celo]: '0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e',
|
|
10313
|
+
[Blockchain.Cronos]: '0x66e428c3f67a68878562e79A0234c1F83c208770',
|
|
10258
10314
|
[Blockchain.Ethereum]: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
|
|
10259
10315
|
[Blockchain.HyperEVM]: '0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb',
|
|
10260
10316
|
[Blockchain.Ink]: '0x0200C29006150606B650577BBE7B6248F58470c1',
|
|
10261
10317
|
[Blockchain.Linea]: '0xA219439258ca9da29E9Cc4cE5596924745e12B93',
|
|
10262
10318
|
[Blockchain.Monad]: '0xe7cd86e13AC4309349F30B3435a9d337750fC82D',
|
|
10319
|
+
[Blockchain.Morph]: '0xe7cd86e13AC4309349F30B3435a9d337750fC82D',
|
|
10263
10320
|
[Blockchain.NEAR]: 'usdt.tether-token.near',
|
|
10264
10321
|
[Blockchain.Optimism]: '0x94b008aA00579c1307B0EF2c499aD98a8ce58e58',
|
|
10265
10322
|
[Blockchain.Polkadot_Asset_Hub]: '1984',
|
|
@@ -10318,6 +10375,7 @@ function parseOrThrow(value, schema, context) {
|
|
|
10318
10375
|
[Blockchain.Arbitrum]: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1',
|
|
10319
10376
|
[Blockchain.Avalanche]: '0xd586E7F844cEa2F87f50152665BCbc2C279D8d70',
|
|
10320
10377
|
[Blockchain.Base]: '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb',
|
|
10378
|
+
[Blockchain.Cronos]: '0xF2001B145b43032AAF5Ee2884e456CCd805F677D',
|
|
10321
10379
|
[Blockchain.Ethereum]: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
|
|
10322
10380
|
[Blockchain.Linea]: '0x4AF15ec2A0BD43Db75dd04E62FAA3B8EF36b00d5',
|
|
10323
10381
|
[Blockchain.Optimism]: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1',
|
|
@@ -10380,7 +10438,9 @@ function parseOrThrow(value, schema, context) {
|
|
|
10380
10438
|
[Blockchain.Arbitrum]: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1',
|
|
10381
10439
|
[Blockchain.Avalanche]: '0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB',
|
|
10382
10440
|
[Blockchain.Base]: '0x4200000000000000000000000000000000000006',
|
|
10441
|
+
[Blockchain.Cronos]: '0xe44Fd7fCb2b1581822D0c862B68222998a0c299a',
|
|
10383
10442
|
[Blockchain.Ethereum]: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
|
|
10443
|
+
[Blockchain.Morph]: '0x5300000000000000000000000000000000000011',
|
|
10384
10444
|
[Blockchain.Optimism]: '0x4200000000000000000000000000000000000006',
|
|
10385
10445
|
[Blockchain.Polygon]: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619',
|
|
10386
10446
|
[Blockchain.Solana]: '7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs'
|
|
@@ -10399,6 +10459,7 @@ function parseOrThrow(value, schema, context) {
|
|
|
10399
10459
|
locators: {
|
|
10400
10460
|
[Blockchain.Ethereum]: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599',
|
|
10401
10461
|
[Blockchain.Arbitrum]: '0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f',
|
|
10462
|
+
[Blockchain.Cronos]: '0x062E66477Faf219F25D27dCED647BF57C3107d52',
|
|
10402
10463
|
[Blockchain.Avalanche]: '0x50b7545627a5162F82A992c33b87aDc75187B218'
|
|
10403
10464
|
}
|
|
10404
10465
|
};
|
|
@@ -12119,6 +12180,39 @@ function resolveOptions(options) {
|
|
|
12119
12180
|
}
|
|
12120
12181
|
};
|
|
12121
12182
|
}
|
|
12183
|
+
/**
|
|
12184
|
+
* Emit telemetry for a completed operation without affecting its caller.
|
|
12185
|
+
*
|
|
12186
|
+
* No-ops when `config.disabled` is `true`. Like {@link withErrorTelemetry},
|
|
12187
|
+
* failures while constructing or submitting the telemetry payload are reported
|
|
12188
|
+
* as a soft warning and never change a completed operation's result.
|
|
12189
|
+
*
|
|
12190
|
+
* @param eventType - The telemetry event type for the completed operation.
|
|
12191
|
+
* @param config - Per-kit SDK identity and disabled flag.
|
|
12192
|
+
* @param context - Optional chain, token, and transaction context.
|
|
12193
|
+
* @returns Nothing.
|
|
12194
|
+
* @throws Never — telemetry failures are reported as warnings.
|
|
12195
|
+
*
|
|
12196
|
+
* @example
|
|
12197
|
+
* ```typescript
|
|
12198
|
+
* import { emitSuccessTelemetry } from '@core/utils'
|
|
12199
|
+
*
|
|
12200
|
+
* emitSuccessTelemetry(
|
|
12201
|
+
* 'bridge_bridge',
|
|
12202
|
+
* { sdkName: 'bridge-kit', sdkVersion: '1.0.0', disabled: false },
|
|
12203
|
+
* { sourceChain: 'Ethereum', destinationChain: 'Base', tokenIn: 'USDC' },
|
|
12204
|
+
* )
|
|
12205
|
+
* ```
|
|
12206
|
+
*/ function emitSuccessTelemetry(eventType, config, context) {
|
|
12207
|
+
if (config.disabled) {
|
|
12208
|
+
return;
|
|
12209
|
+
}
|
|
12210
|
+
try {
|
|
12211
|
+
void emitAnalyticsLog(buildPayload(config, eventType, undefined, context));
|
|
12212
|
+
} catch (telemetryError) {
|
|
12213
|
+
warnTelemetryDrop(eventType, telemetryError);
|
|
12214
|
+
}
|
|
12215
|
+
}
|
|
12122
12216
|
/**
|
|
12123
12217
|
* Wrap an async operation with error telemetry.
|
|
12124
12218
|
*
|
|
@@ -12229,7 +12323,7 @@ function resolveOptions(options) {
|
|
|
12229
12323
|
}
|
|
12230
12324
|
|
|
12231
12325
|
var name$3 = "@circle-fin/bridge-kit";
|
|
12232
|
-
var version$4 = "1.
|
|
12326
|
+
var version$4 = "1.16.0";
|
|
12233
12327
|
var pkg$4 = {
|
|
12234
12328
|
name: name$3,
|
|
12235
12329
|
version: version$4};
|
|
@@ -13490,6 +13584,53 @@ const EURC_MAINNET_TOKEN_ID = '0x6ca9e29fa53becc29becaf4a90b9ca7a995ad4d2234880d
|
|
|
13490
13584
|
}
|
|
13491
13585
|
};
|
|
13492
13586
|
|
|
13587
|
+
/**
|
|
13588
|
+
* Map a CCTPx bytes32 token id back to its known display symbol.
|
|
13589
|
+
*
|
|
13590
|
+
* The inverse of the provider's internal symbol -> id resolution: a bridge
|
|
13591
|
+
* resolves a symbol such as `'cirBTC'` to its canonical bytes32 id and reports
|
|
13592
|
+
* that id on `result.token`, dropping the symbol. This helper recovers the
|
|
13593
|
+
* symbol for display. It is scoped to {@link KNOWN_TOKEN_SYMBOLS} — the same
|
|
13594
|
+
* known set the forward resolution covers — and is keyed by network, because a
|
|
13595
|
+
* symbol names a separate registration on each network, whose ids are
|
|
13596
|
+
* unrelated.
|
|
13597
|
+
*
|
|
13598
|
+
* The lookup is best-effort by design: an arbitrary registry token, a
|
|
13599
|
+
* non-canonical bridge of a known symbol, or any unrecognized id has no known
|
|
13600
|
+
* symbol and yields `undefined`. The id is matched case-insensitively (bytes32
|
|
13601
|
+
* ids have no checksum casing).
|
|
13602
|
+
*
|
|
13603
|
+
* @param id - The bytes32 token id to decode (e.g. a `result.token` value).
|
|
13604
|
+
* @param network - The network the id belongs to (`'testnet'` or `'mainnet'`);
|
|
13605
|
+
* derive it from the source chain, e.g. `chain.isTestnet ? 'testnet' :
|
|
13606
|
+
* 'mainnet'`.
|
|
13607
|
+
* @returns The matching {@link KnownTokenSymbol}, or `undefined` when `id` is
|
|
13608
|
+
* not one of the known canonical ids for `network`.
|
|
13609
|
+
* @throws A `KitError` (`INPUT_VALIDATION_FAILED`, FATAL) when `id` is not a
|
|
13610
|
+
* string or `network` is not a recognized network.
|
|
13611
|
+
*
|
|
13612
|
+
* @example
|
|
13613
|
+
* ```typescript
|
|
13614
|
+
* import { resolveToKnownTokenSymbol } from '@circle-fin/provider-cctpx'
|
|
13615
|
+
*
|
|
13616
|
+
* const result = await provider.bridge(params) // params.token === 'cirBTC'
|
|
13617
|
+
* const network = result.source.chain.isTestnet ? 'testnet' : 'mainnet'
|
|
13618
|
+
*
|
|
13619
|
+
* resolveToKnownTokenSymbol(result.token, network) // 'cirBTC'
|
|
13620
|
+
* resolveToKnownTokenSymbol('0xdeadbeef…', network) // undefined (not known)
|
|
13621
|
+
* ```
|
|
13622
|
+
*/ function resolveToKnownTokenSymbol(id, network) {
|
|
13623
|
+
if (typeof id !== 'string') {
|
|
13624
|
+
throw createValidationFailedError$1('id', id, 'must be a string');
|
|
13625
|
+
}
|
|
13626
|
+
if (network !== 'testnet' && network !== 'mainnet') {
|
|
13627
|
+
throw createValidationFailedError$1('network', network, "must be 'testnet' or 'mainnet'");
|
|
13628
|
+
}
|
|
13629
|
+
const row = KNOWN_TOKEN_IDS_BY_NETWORK[network];
|
|
13630
|
+
const target = id.toLowerCase();
|
|
13631
|
+
return KNOWN_TOKEN_SYMBOLS.find((symbol)=>row[symbol].toLowerCase() === target);
|
|
13632
|
+
}
|
|
13633
|
+
|
|
13493
13634
|
/**
|
|
13494
13635
|
* Default clock implementation.
|
|
13495
13636
|
*
|
|
@@ -14794,7 +14935,11 @@ function createNoopLogger() {
|
|
|
14794
14935
|
tokenId: bytes32Hex,
|
|
14795
14936
|
domainId: nonNegativeInteger,
|
|
14796
14937
|
tokenAddress: z.string(),
|
|
14797
|
-
tokenManagerAddress: z.string()
|
|
14938
|
+
tokenManagerAddress: z.string(),
|
|
14939
|
+
// Operator-controlled per-chain kill switch (CCTPE-3979). Optional for
|
|
14940
|
+
// back-compat with older IRIS versions that do not surface it. Downstream
|
|
14941
|
+
// consumers in `findCCTPXDeployment` treat a missing value as `true`.
|
|
14942
|
+
enabled: z.boolean().optional()
|
|
14798
14943
|
});
|
|
14799
14944
|
/**
|
|
14800
14945
|
* Schema for one token entry in the token registry response.
|
|
@@ -15278,17 +15423,23 @@ function createNoopLogger() {
|
|
|
15278
15423
|
/**
|
|
15279
15424
|
* Find a token's deployment on the given CCTP domain.
|
|
15280
15425
|
*
|
|
15426
|
+
* A deployment row with `enabled === false` is treated as missing: an IRIS
|
|
15427
|
+
* operator has flipped the per-chain kill switch (CCTPE-3979), so the SDK must
|
|
15428
|
+
* not route through it even though the row still exists in the registry. A
|
|
15429
|
+
* missing or `true` `enabled` value remains routable — the field is optional on
|
|
15430
|
+
* older IRIS versions and absence is read as "allowed".
|
|
15431
|
+
*
|
|
15281
15432
|
* @param token - The registry token whose deployments are searched.
|
|
15282
15433
|
* @param domain - The CCTP domain id to match.
|
|
15283
15434
|
* @returns The matching {@link CCTPXTokenDeployment}, or `undefined` when the
|
|
15284
|
-
* token has no deployment on that domain.
|
|
15435
|
+
* token has no deployment on that domain or the deployment is disabled.
|
|
15285
15436
|
*
|
|
15286
15437
|
* @example
|
|
15287
15438
|
* ```typescript
|
|
15288
15439
|
* const deployment = findCCTPXDeployment(token, 0)
|
|
15289
15440
|
* ```
|
|
15290
15441
|
*/ function findCCTPXDeployment(token, domain) {
|
|
15291
|
-
return token.deployments.find((deployment)=>deployment.domainId === domain);
|
|
15442
|
+
return token.deployments.find((deployment)=>deployment.domainId === domain && deployment.enabled !== false);
|
|
15292
15443
|
}
|
|
15293
15444
|
|
|
15294
15445
|
/**
|
|
@@ -15390,6 +15541,24 @@ function createNoopLogger() {
|
|
|
15390
15541
|
}
|
|
15391
15542
|
}
|
|
15392
15543
|
})
|
|
15544
|
+
],
|
|
15545
|
+
// The token is not deployed on one of the route chains, or an operator has
|
|
15546
|
+
// flipped the per-chain `enabled` kill switch on the IRIS deployment row.
|
|
15547
|
+
// Either way the route is permanently unavailable until the operator intervenes;
|
|
15548
|
+
// a retry at the same source/destination will keep returning this error.
|
|
15549
|
+
[
|
|
15550
|
+
'TOKEN_NOT_SUPPORTED_ON_ROUTE',
|
|
15551
|
+
({ sourceDomain, destinationDomain })=>new KitError({
|
|
15552
|
+
...InputError.UNSUPPORTED_ROUTE,
|
|
15553
|
+
recoverability: 'FATAL',
|
|
15554
|
+
message: 'CCTPx fee quote rejected the route: the token is not supported on ' + 'the source or destination chain (missing deployment or operator-disabled).',
|
|
15555
|
+
cause: {
|
|
15556
|
+
trace: {
|
|
15557
|
+
sourceDomain,
|
|
15558
|
+
destinationDomain
|
|
15559
|
+
}
|
|
15560
|
+
}
|
|
15561
|
+
})
|
|
15393
15562
|
]
|
|
15394
15563
|
]);
|
|
15395
15564
|
/**
|
|
@@ -20646,6 +20815,24 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
|
|
|
20646
20815
|
}
|
|
20647
20816
|
};
|
|
20648
20817
|
|
|
20818
|
+
/**
|
|
20819
|
+
* Check whether a forwarded burn to the given destination asks Circle's
|
|
20820
|
+
* Forwarding Service to set up the recipient's token account before minting.
|
|
20821
|
+
*
|
|
20822
|
+
* Must return `true` exactly for the destinations where
|
|
20823
|
+
* {@link getForwarderHookData} emits the `createAta` frame, so the forwarding
|
|
20824
|
+
* fee quote includes the setup rent whenever the burn requests it.
|
|
20825
|
+
*
|
|
20826
|
+
* @internal
|
|
20827
|
+
* @param chainType - The destination blockchain type.
|
|
20828
|
+
* @returns `true` for Solana destinations, `false` otherwise.
|
|
20829
|
+
*
|
|
20830
|
+
* @example
|
|
20831
|
+
* ```typescript
|
|
20832
|
+
* requiresRecipientSetup('solana') // true
|
|
20833
|
+
* requiresRecipientSetup('evm') // false
|
|
20834
|
+
* ```
|
|
20835
|
+
*/ const requiresRecipientSetup = (chainType)=>chainType === 'solana';
|
|
20649
20836
|
/**
|
|
20650
20837
|
* Build the forwarding `hookData` for a forwarded (Orbit-relayed) CCTP v2 burn,
|
|
20651
20838
|
* tailored to the destination chain.
|
|
@@ -20996,10 +21183,12 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
|
|
|
20996
21183
|
* @param sourceDomain - The source domain
|
|
20997
21184
|
* @param destinationDomain - The destination domain
|
|
20998
21185
|
* @param isTestnet - Whether the request is for a testnet chain
|
|
21186
|
+
* @param includeRecipientSetup - Whether the quote includes recipient account setup rent
|
|
20999
21187
|
* @returns The complete API URL with forward=true query parameter
|
|
21000
|
-
*/ function buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet) {
|
|
21188
|
+
*/ function buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet, includeRecipientSetup) {
|
|
21001
21189
|
const baseUrl = isTestnet ? IRIS_API_SANDBOX_BASE_URL$1 : IRIS_API_BASE_URL$1;
|
|
21002
|
-
|
|
21190
|
+
const recipientSetupQuery = includeRecipientSetup ? '&includeRecipientSetup=true' : '';
|
|
21191
|
+
return `${baseUrl}/v2/burn/USDC/fees/${sourceDomain.toString()}/${destinationDomain.toString()}?forward=true${recipientSetupQuery}`;
|
|
21003
21192
|
}
|
|
21004
21193
|
/**
|
|
21005
21194
|
* Fetches the forwarding fee for a USDC transfer operation with retry and timeout handling.
|
|
@@ -21016,6 +21205,10 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
|
|
|
21016
21205
|
*
|
|
21017
21206
|
* The high fee tier is always used to provide buffer for destination gas fluctuations.
|
|
21018
21207
|
*
|
|
21208
|
+
* Pass `includeRecipientSetup: true` when the burn asks the Forwarding Service to create
|
|
21209
|
+
* the recipient's token account (Solana destinations). The quote then includes the
|
|
21210
|
+
* account rent, which the quote without this flag leaves out.
|
|
21211
|
+
*
|
|
21019
21212
|
* Implements timeout and retry logic to handle network issues and temporary API failures.
|
|
21020
21213
|
* Each HTTP request is given a maximum of 2 seconds before it is aborted.
|
|
21021
21214
|
* We retry up to 10 times, waiting 200ms between attempts.
|
|
@@ -21024,6 +21217,8 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
|
|
|
21024
21217
|
* @param destinationDomain - The destination domain
|
|
21025
21218
|
* @param isTestnet - Whether the request is for a testnet chain
|
|
21026
21219
|
* @param finalityThreshold - The finality threshold to select the fee tier (1000 for FAST, 2000 for SLOW)
|
|
21220
|
+
* @param includeRecipientSetup - Whether to include recipient account setup rent in the
|
|
21221
|
+
* quote. Defaults to `false`.
|
|
21027
21222
|
* @returns The high-tier forwarding fee in USDC minor units (6 decimals)
|
|
21028
21223
|
* @throws Error if the input domains are invalid, the API request fails, returns invalid data, or network errors occur
|
|
21029
21224
|
*
|
|
@@ -21035,8 +21230,11 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
|
|
|
21035
21230
|
*
|
|
21036
21231
|
* // SLOW transfer - use 2000ms finality threshold
|
|
21037
21232
|
* const slowForwardingFee = await fetchForwardingFee(0, 6, false, 2000)
|
|
21233
|
+
*
|
|
21234
|
+
* // Ethereum -> Solana: include the recipient token account rent
|
|
21235
|
+
* const solanaForwardingFee = await fetchForwardingFee(0, 5, false, 1000, true)
|
|
21038
21236
|
* ```
|
|
21039
|
-
*/ async function fetchForwardingFee(sourceDomain, destinationDomain, isTestnet, finalityThreshold) {
|
|
21237
|
+
*/ async function fetchForwardingFee(sourceDomain, destinationDomain, isTestnet, finalityThreshold, includeRecipientSetup = false) {
|
|
21040
21238
|
// Validate source domain
|
|
21041
21239
|
if (!Number.isInteger(sourceDomain) || sourceDomain < 0) {
|
|
21042
21240
|
throw new KitError({
|
|
@@ -21064,7 +21262,7 @@ const FAST_TIER_FINALITY_THRESHOLD = 1000;
|
|
|
21064
21262
|
});
|
|
21065
21263
|
}
|
|
21066
21264
|
// Fetch the fee tiers from the API with forward=true
|
|
21067
|
-
const url = buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet);
|
|
21265
|
+
const url = buildForwardingFeeUrl(sourceDomain, destinationDomain, isTestnet, includeRecipientSetup);
|
|
21068
21266
|
const response = await pollApiGet(url, isForwardingFeeResponse, DEFAULT_CONFIG$1);
|
|
21069
21267
|
// Validate that we have at least one fee tier
|
|
21070
21268
|
if (response.length === 0) {
|
|
@@ -23400,7 +23598,7 @@ const mockAttestationMessage = {
|
|
|
23400
23598
|
return step;
|
|
23401
23599
|
}
|
|
23402
23600
|
|
|
23403
|
-
var version$3 = "1.14.
|
|
23601
|
+
var version$3 = "1.14.3";
|
|
23404
23602
|
var pkg$3 = {
|
|
23405
23603
|
version: version$3};
|
|
23406
23604
|
|
|
@@ -24319,9 +24517,34 @@ function assertCCTPV2Config(config) {
|
|
|
24319
24517
|
tokenAddress: source.chain.usdcAddress,
|
|
24320
24518
|
operationContext: sourceOperationContext
|
|
24321
24519
|
});
|
|
24520
|
+
await this.assertAmountCoversRecipientSetupFee(params);
|
|
24322
24521
|
return bridge$1(params, this);
|
|
24323
24522
|
}
|
|
24324
24523
|
/**
|
|
24524
|
+
* Reject a forwarded transfer to Solana whose amount does not exceed the fee.
|
|
24525
|
+
*
|
|
24526
|
+
* CCTP v2 reverts a burn whose `maxFee` is not less than its amount, and the Solana
|
|
24527
|
+
* forwarding fee includes the recipient token account rent. Checking before the
|
|
24528
|
+
* approval avoids sending a transaction that can never be followed by a burn.
|
|
24529
|
+
* Skipped when the caller provides `config.maxFee`.
|
|
24530
|
+
*
|
|
24531
|
+
* @param params - The validated CCTP v2 bridge parameters.
|
|
24532
|
+
* @returns A promise that resolves when the amount covers the fee.
|
|
24533
|
+
* @throws {KitError} INPUT_INVALID_AMOUNT (FATAL) when the fee is greater than or equal
|
|
24534
|
+
* to the amount.
|
|
24535
|
+
*/ async assertAmountCoversRecipientSetupFee(params) {
|
|
24536
|
+
const { destination, amount, config } = params;
|
|
24537
|
+
if (destination.useForwarder !== true || config.maxFee !== undefined || !requiresRecipientSetup(destination.chain.type)) {
|
|
24538
|
+
return;
|
|
24539
|
+
}
|
|
24540
|
+
const { providerFee, forwarderFee } = await this.getMaxFee(params);
|
|
24541
|
+
const maxFee = providerFee + forwarderFee;
|
|
24542
|
+
if (maxFee >= BigInt(amount)) {
|
|
24543
|
+
// Amounts and fees are in USDC minor units (6 decimals)
|
|
24544
|
+
throw createInvalidAmountError(formatUnits(amount, 6), `Amount must be greater than the ${formatUnits(String(maxFee), 6)} USDC fee for forwarded transfers to ${destination.chain.name}, which includes creating the recipient's token account`);
|
|
24545
|
+
}
|
|
24546
|
+
}
|
|
24547
|
+
/**
|
|
24325
24548
|
* Retry a failed or incomplete CCTP v2 bridge operation.
|
|
24326
24549
|
*
|
|
24327
24550
|
* Analyzes the bridge result to determine where to continue and executes
|
|
@@ -25038,6 +25261,9 @@ function assertCCTPV2Config(config) {
|
|
|
25038
25261
|
* | FAST | true | No | maxFee = calculatedBurnFee + forwardingFee |
|
|
25039
25262
|
* | FAST | true | Yes | maxFee = config.maxFee |
|
|
25040
25263
|
*
|
|
25264
|
+
* For forwarded burns to Solana, the forwarding fee includes the rent for creating the
|
|
25265
|
+
* recipient's token account. A caller-provided `maxFee` must cover it too.
|
|
25266
|
+
*
|
|
25041
25267
|
* @param params - The bridge parameters object containing:
|
|
25042
25268
|
* - `source`: The source wallet context with chain definition and adapter
|
|
25043
25269
|
* - `destination`: The destination wallet context with chain definition and adapter
|
|
@@ -25076,6 +25302,7 @@ function assertCCTPV2Config(config) {
|
|
|
25076
25302
|
}
|
|
25077
25303
|
// Get the min finality threshold based on the transfer speed
|
|
25078
25304
|
const minFinalityThreshold = CCTPv2MinFinalityThreshold[transferSpeed];
|
|
25305
|
+
const includeRecipientSetup = requiresRecipientSetup(destination.chain.type);
|
|
25079
25306
|
// SLOW transfer without forwarder: no fee
|
|
25080
25307
|
if (transferSpeed === TransferSpeed.SLOW && !useForwarder) {
|
|
25081
25308
|
return {
|
|
@@ -25085,7 +25312,7 @@ function assertCCTPV2Config(config) {
|
|
|
25085
25312
|
}
|
|
25086
25313
|
// SLOW transfer with forwarder: only forwarding fee
|
|
25087
25314
|
if (transferSpeed === TransferSpeed.SLOW && useForwarder) {
|
|
25088
|
-
const forwarderFee = await fetchForwardingFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet, minFinalityThreshold);
|
|
25315
|
+
const forwarderFee = await fetchForwardingFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet, minFinalityThreshold, includeRecipientSetup);
|
|
25089
25316
|
return {
|
|
25090
25317
|
providerFee: 0n,
|
|
25091
25318
|
forwarderFee
|
|
@@ -25095,7 +25322,7 @@ function assertCCTPV2Config(config) {
|
|
|
25095
25322
|
// Fetch fees in parallel when forwarder is enabled
|
|
25096
25323
|
const [scaledBps, forwarderFee] = await Promise.all([
|
|
25097
25324
|
fetchUsdcFastBurnFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet),
|
|
25098
|
-
useForwarder ? fetchForwardingFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet, minFinalityThreshold) : Promise.resolve(0n)
|
|
25325
|
+
useForwarder ? fetchForwardingFee(source.chain.cctp.domain, destination.chain.cctp.domain, source.chain.isTestnet, minFinalityThreshold, includeRecipientSetup) : Promise.resolve(0n)
|
|
25099
25326
|
]);
|
|
25100
25327
|
// Calculate fee proportional to the transfer amount
|
|
25101
25328
|
const amountInMinorUnits = BigInt(amount);
|
|
@@ -25645,6 +25872,21 @@ function assertCCTPV2Config(config) {
|
|
|
25645
25872
|
'bridge_forward'
|
|
25646
25873
|
]
|
|
25647
25874
|
];
|
|
25875
|
+
/**
|
|
25876
|
+
* Provider step names whose `txHash` is the source-chain transaction that
|
|
25877
|
+
* moves funds into the bridge protocol.
|
|
25878
|
+
*
|
|
25879
|
+
* @remarks
|
|
25880
|
+
* The success event carries this hash so the backend can join it to the
|
|
25881
|
+
* on-chain CCTP / CCTPx event for the same transfer. `burn` is the CCTP v2
|
|
25882
|
+
* step (including batched and source-fee flows); `transfer` is the CCTPx
|
|
25883
|
+
* `CrossChainTokenService` step.
|
|
25884
|
+
*
|
|
25885
|
+
* @internal
|
|
25886
|
+
*/ const BRIDGE_SOURCE_TX_STEP_NAMES = [
|
|
25887
|
+
'burn',
|
|
25888
|
+
'transfer'
|
|
25889
|
+
];
|
|
25648
25890
|
|
|
25649
25891
|
/**
|
|
25650
25892
|
* Base URL for Circle's Quote API (hosted in Iris) on mainnet/production.
|
|
@@ -26702,6 +26944,85 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
26702
26944
|
}
|
|
26703
26945
|
return undefined;
|
|
26704
26946
|
}
|
|
26947
|
+
/**
|
|
26948
|
+
* Pick the source-chain transaction hash from a bridge result.
|
|
26949
|
+
*
|
|
26950
|
+
* Walk the steps from the end and return the hash of the most recent
|
|
26951
|
+
* successful source step (`burn` for CCTP v2, `transfer` for CCTPx). Walking
|
|
26952
|
+
* backwards selects the attempt that landed when a retry appended a new
|
|
26953
|
+
* source step after a failed one.
|
|
26954
|
+
*
|
|
26955
|
+
* @param steps - All steps from the bridge result.
|
|
26956
|
+
* @returns The source transaction hash, or `undefined` if no source step recorded one.
|
|
26957
|
+
*
|
|
26958
|
+
* @internal
|
|
26959
|
+
*/ function pickSourceTxHash(steps) {
|
|
26960
|
+
for(let i = steps.length - 1; i >= 0; i--){
|
|
26961
|
+
const step = steps[i];
|
|
26962
|
+
if (step?.txHash != null && step.state === 'success' && BRIDGE_SOURCE_TX_STEP_NAMES.includes(step.name)) {
|
|
26963
|
+
return step.txHash;
|
|
26964
|
+
}
|
|
26965
|
+
}
|
|
26966
|
+
return undefined;
|
|
26967
|
+
}
|
|
26968
|
+
/**
|
|
26969
|
+
* Resolve the token value reported in telemetry.
|
|
26970
|
+
*
|
|
26971
|
+
* CCTPx reports `result.token` as a bytes32 token id, while the backend's
|
|
26972
|
+
* canonical tables key tokens by symbol. Map the canonical id of a known CCTPx
|
|
26973
|
+
* token back to its symbol and pass any other value (USDC, or a registry token
|
|
26974
|
+
* without a known symbol) through unchanged. Registry symbols are not used
|
|
26975
|
+
* because they are not unique across CCTPx tokens. Never throws.
|
|
26976
|
+
*
|
|
26977
|
+
* @param token - The token from a bridge result.
|
|
26978
|
+
* @param sourceChain - The result's source chain; selects testnet or mainnet ids.
|
|
26979
|
+
* @returns The known symbol, or `token` unchanged.
|
|
26980
|
+
*
|
|
26981
|
+
* @internal
|
|
26982
|
+
*/ function toTelemetryToken(token, sourceChain) {
|
|
26983
|
+
try {
|
|
26984
|
+
const network = sourceChain.isTestnet ? 'testnet' : 'mainnet';
|
|
26985
|
+
return resolveToKnownTokenSymbol(token, network) ?? token;
|
|
26986
|
+
} catch {
|
|
26987
|
+
return token;
|
|
26988
|
+
}
|
|
26989
|
+
}
|
|
26990
|
+
/**
|
|
26991
|
+
* Emit the `bridge_bridge` success event for a completed transfer.
|
|
26992
|
+
*
|
|
26993
|
+
* No-ops unless `result.state` is `'success'`. Failed results are already
|
|
26994
|
+
* reported by error telemetry. Never throws: a malformed result (for example
|
|
26995
|
+
* from a custom provider) is reported as a telemetry drop warning and the
|
|
26996
|
+
* caller's result is returned unchanged.
|
|
26997
|
+
*
|
|
26998
|
+
* @param result - The human-readable bridge result returned to the caller.
|
|
26999
|
+
* @param config - Analytics telemetry identity, gated by `disableAnalytics`.
|
|
27000
|
+
*
|
|
27001
|
+
* @internal
|
|
27002
|
+
*/ function emitBridgeSuccessTelemetry(result, config) {
|
|
27003
|
+
if (config.disabled || result.state !== 'success') {
|
|
27004
|
+
return;
|
|
27005
|
+
}
|
|
27006
|
+
try {
|
|
27007
|
+
const txHash = pickSourceTxHash(result.steps);
|
|
27008
|
+
// `JSON.stringify` turns a non-finite number into `null`, which the logs
|
|
27009
|
+
// endpoint's strict schema rejects along with the whole event.
|
|
27010
|
+
const amountIn = Number.parseFloat(result.amount);
|
|
27011
|
+
emitSuccessTelemetry(BRIDGE_EVENT_TYPES.BRIDGE, config, {
|
|
27012
|
+
sourceChain: result.source.chain.chain,
|
|
27013
|
+
destinationChain: result.destination.chain.chain,
|
|
27014
|
+
tokenIn: toTelemetryToken(result.token, result.source.chain),
|
|
27015
|
+
...Number.isFinite(amountIn) && {
|
|
27016
|
+
amountIn
|
|
27017
|
+
},
|
|
27018
|
+
...txHash != null && {
|
|
27019
|
+
txHash
|
|
27020
|
+
}
|
|
27021
|
+
});
|
|
27022
|
+
} catch (telemetryError) {
|
|
27023
|
+
warnTelemetryDrop(BRIDGE_EVENT_TYPES.BRIDGE, telemetryError);
|
|
27024
|
+
}
|
|
27025
|
+
}
|
|
26705
27026
|
/**
|
|
26706
27027
|
* BridgeKit caller component for retry and estimate operations.
|
|
26707
27028
|
*/ const BRIDGE_KIT_CALLER = {
|
|
@@ -26832,6 +27153,10 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
26832
27153
|
/** Whether error telemetry is disabled. */ disableErrorReporting;
|
|
26833
27154
|
/** Per-kit telemetry identity for shared helpers. */ telemetryConfig;
|
|
26834
27155
|
/**
|
|
27156
|
+
* Per-kit telemetry identity for success events. Gated by `disableAnalytics`
|
|
27157
|
+
* independently of `disableErrorReporting`.
|
|
27158
|
+
*/ analyticsTelemetryConfig;
|
|
27159
|
+
/**
|
|
26835
27160
|
* Create a new BridgeKit instance.
|
|
26836
27161
|
*
|
|
26837
27162
|
* @param config - The configuration containing the CCTPv2 provider
|
|
@@ -26858,6 +27183,11 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
26858
27183
|
sdkVersion: pkg$4.version,
|
|
26859
27184
|
disabled: this.disableErrorReporting
|
|
26860
27185
|
};
|
|
27186
|
+
this.analyticsTelemetryConfig = {
|
|
27187
|
+
sdkName: SDK_NAME,
|
|
27188
|
+
sdkVersion: pkg$4.version,
|
|
27189
|
+
disabled: config.disableAnalytics === true
|
|
27190
|
+
};
|
|
26861
27191
|
for (const provider of this.providers){
|
|
26862
27192
|
provider.registerDispatcher(this.actionDispatcher);
|
|
26863
27193
|
}
|
|
@@ -26871,7 +27201,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
26871
27201
|
this.actionDispatcher.off(actionOrWildCard, handler);
|
|
26872
27202
|
}
|
|
26873
27203
|
async bridge(params) {
|
|
26874
|
-
|
|
27204
|
+
const bridgeResult = await withErrorTelemetry(async ()=>{
|
|
26875
27205
|
// First validate the parameters
|
|
26876
27206
|
assertBridgeParams(params, bridgeParamsWithChainIdentifierSchema);
|
|
26877
27207
|
// Then resolve chain definitions (includes adapter chain support validation)
|
|
@@ -26908,7 +27238,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
26908
27238
|
emitResultStepErrorTelemetry(failedStep, BRIDGE_STEP_EVENT_MAP, BRIDGE_EVENT_TYPES.BRIDGE, this.telemetryConfig, {
|
|
26909
27239
|
sourceChain: resolveChainName(params.from.chain),
|
|
26910
27240
|
destinationChain: resolveChainName(params.to.chain),
|
|
26911
|
-
tokenIn:
|
|
27241
|
+
tokenIn: toTelemetryToken(result.token, result.source.chain),
|
|
26912
27242
|
...txHash != null && {
|
|
26913
27243
|
txHash
|
|
26914
27244
|
}
|
|
@@ -26920,6 +27250,8 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
26920
27250
|
destinationChain: resolveChainName(params.to.chain),
|
|
26921
27251
|
tokenIn: params.token
|
|
26922
27252
|
});
|
|
27253
|
+
emitBridgeSuccessTelemetry(bridgeResult, this.analyticsTelemetryConfig);
|
|
27254
|
+
return bridgeResult;
|
|
26923
27255
|
}
|
|
26924
27256
|
/**
|
|
26925
27257
|
* Retry a failed or incomplete cross-chain USDC bridge operation.
|
|
@@ -26990,7 +27322,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
26990
27322
|
* )
|
|
26991
27323
|
* ```
|
|
26992
27324
|
*/ async retry(result, context, invocationMeta) {
|
|
26993
|
-
|
|
27325
|
+
const retriedResult = await withErrorTelemetry(async ()=>{
|
|
26994
27326
|
// Cast the providers list to the wide view here. The tuple
|
|
26995
27327
|
// type on `this.providers` retains concrete provider types
|
|
26996
27328
|
// (CCTPv2 narrows `TToken` to `'USDC'`); calling `.retry`
|
|
@@ -27018,7 +27350,7 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
27018
27350
|
emitResultStepErrorTelemetry(failedStep, BRIDGE_STEP_EVENT_MAP, BRIDGE_EVENT_TYPES.RETRY, this.telemetryConfig, {
|
|
27019
27351
|
sourceChain: result.source.chain.chain,
|
|
27020
27352
|
destinationChain: result.destination.chain.chain,
|
|
27021
|
-
tokenIn: result.token,
|
|
27353
|
+
tokenIn: toTelemetryToken(result.token, result.source.chain),
|
|
27022
27354
|
...txHash != null && {
|
|
27023
27355
|
txHash
|
|
27024
27356
|
}
|
|
@@ -27032,8 +27364,16 @@ async function resolveExecutionQuote(binding, suppliedQuote, refundAddress) {
|
|
|
27032
27364
|
}, BRIDGE_EVENT_TYPES.RETRY, this.telemetryConfig, {
|
|
27033
27365
|
sourceChain: result.source.chain.chain,
|
|
27034
27366
|
destinationChain: result.destination.chain.chain,
|
|
27035
|
-
tokenIn: result.token
|
|
27367
|
+
tokenIn: toTelemetryToken(result.token, result.source.chain)
|
|
27036
27368
|
});
|
|
27369
|
+
// A retry that completes the transfer is the transfer's only success
|
|
27370
|
+
// event, so it reports the same `bridge_bridge` type as `bridge()`. An
|
|
27371
|
+
// input that already succeeded was reported by the call that completed it
|
|
27372
|
+
// (CCTP v2 returns such a result unchanged), so it is not reported again.
|
|
27373
|
+
if (result.state !== 'success') {
|
|
27374
|
+
emitBridgeSuccessTelemetry(retriedResult, this.analyticsTelemetryConfig);
|
|
27375
|
+
}
|
|
27376
|
+
return retriedResult;
|
|
27037
27377
|
}
|
|
27038
27378
|
async estimate(params) {
|
|
27039
27379
|
return withErrorTelemetry(async ()=>{
|
|
@@ -27629,6 +27969,9 @@ registerKit(`${pkg$4.name}/${pkg$4.version}`);
|
|
|
27629
27969
|
...context.disableErrorReporting != null && {
|
|
27630
27970
|
disableErrorReporting: context.disableErrorReporting
|
|
27631
27971
|
},
|
|
27972
|
+
...context.disableAnalytics != null && {
|
|
27973
|
+
disableAnalytics: context.disableAnalytics
|
|
27974
|
+
},
|
|
27632
27975
|
...context.headers != null && {
|
|
27633
27976
|
headers: context.headers
|
|
27634
27977
|
}
|
|
@@ -27651,7 +27994,7 @@ registerKit(`${pkg$4.name}/${pkg$4.version}`);
|
|
|
27651
27994
|
};
|
|
27652
27995
|
|
|
27653
27996
|
var name$2 = "@circle-fin/swap-kit";
|
|
27654
|
-
var version$2 = "1.
|
|
27997
|
+
var version$2 = "1.8.1";
|
|
27655
27998
|
var pkg$2 = {
|
|
27656
27999
|
name: name$2,
|
|
27657
28000
|
version: version$2};
|
|
@@ -27993,6 +28336,64 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
|
|
|
27993
28336
|
}, {
|
|
27994
28337
|
message: 'fee amount must be non-negative (>= 0)'
|
|
27995
28338
|
});
|
|
28339
|
+
/**
|
|
28340
|
+
* Parses a display-only field leniently: a value `schema` rejects is replaced
|
|
28341
|
+
* with `fallback` instead of failing the response that carries it.
|
|
28342
|
+
* Implemented with `preprocess` rather than Zod's `.catch()` because static
|
|
28343
|
+
* analysis misreads `.catch` on the schema chain as an unhandled Promise
|
|
28344
|
+
* (S7785).
|
|
28345
|
+
*/ const withFallback = (schema, fallback)=>z.preprocess((value)=>schema.safeParse(value).success ? value : fallback, schema);
|
|
28346
|
+
const swapRouteTokenSchema = z.object({
|
|
28347
|
+
symbol: z.string(),
|
|
28348
|
+
address: z.string(),
|
|
28349
|
+
decimals: z.number()
|
|
28350
|
+
});
|
|
28351
|
+
const swapRouteMetadataSchema = z.record(z.unknown()).optional();
|
|
28352
|
+
const swapRouteStepSchema = z.object({
|
|
28353
|
+
type: z.string(),
|
|
28354
|
+
tool: z.string(),
|
|
28355
|
+
toolName: z.string(),
|
|
28356
|
+
fromToken: swapRouteTokenSchema,
|
|
28357
|
+
toToken: swapRouteTokenSchema,
|
|
28358
|
+
estimate: z.object({
|
|
28359
|
+
fromAmount: z.string(),
|
|
28360
|
+
toAmount: z.string(),
|
|
28361
|
+
gasCostUSD: z.string().optional()
|
|
28362
|
+
}),
|
|
28363
|
+
metadata: swapRouteMetadataSchema
|
|
28364
|
+
});
|
|
28365
|
+
/**
|
|
28366
|
+
* Strict schema for a `SwapRoute`. Module-private: service responses
|
|
28367
|
+
* parse routes leniently through {@link responseSwapRouteSchema}.
|
|
28368
|
+
*/ const swapRouteSchema = z.object({
|
|
28369
|
+
provider: z.string().min(1, 'provider must be a non-empty string'),
|
|
28370
|
+
steps: z.array(swapRouteStepSchema),
|
|
28371
|
+
metadata: swapRouteMetadataSchema
|
|
28372
|
+
});
|
|
28373
|
+
/**
|
|
28374
|
+
* Route details are display-only, so service responses parse them leniently:
|
|
28375
|
+
* steps or metadata in a shape the SDK does not know are dropped rather than
|
|
28376
|
+
* failing the quote or swap they describe. Steps are all-or-nothing: if any
|
|
28377
|
+
* step is malformed, `steps` is empty, so a route never silently loses a hop.
|
|
28378
|
+
*/ const responseSwapRouteSchema = swapRouteSchema.extend({
|
|
28379
|
+
steps: withFallback(swapRouteSchema.shape.steps, []),
|
|
28380
|
+
metadata: withFallback(swapRouteMetadataSchema, undefined)
|
|
28381
|
+
});
|
|
28382
|
+
const createSwapFeeItemSchema = z.object({
|
|
28383
|
+
token: z.string({
|
|
28384
|
+
required_error: 'fee token is required',
|
|
28385
|
+
invalid_type_error: 'fee token must be a string'
|
|
28386
|
+
}).min(1, 'fee token must be a non-empty string'),
|
|
28387
|
+
amount: feeAmountSchema,
|
|
28388
|
+
decimals: z.number().int('fee token decimals must be an integer').nonnegative('fee token decimals must be a non-negative integer').optional(),
|
|
28389
|
+
symbol: z.string({
|
|
28390
|
+
invalid_type_error: 'fee token symbol must be a string'
|
|
28391
|
+
}).min(1, 'fee token symbol must be a non-empty string').optional(),
|
|
28392
|
+
// Descriptive metadata: a value the SDK cannot use is dropped rather than
|
|
28393
|
+
// failing the response that carries the fee.
|
|
28394
|
+
type: withFallback(z.string().min(1).optional(), undefined),
|
|
28395
|
+
chain: withFallback(z.string().min(1).optional(), undefined)
|
|
28396
|
+
});
|
|
27996
28397
|
/**
|
|
27997
28398
|
* Zod schema for validating API keys.
|
|
27998
28399
|
*
|
|
@@ -28078,10 +28479,7 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
|
|
|
28078
28479
|
/** Quote information with estimated amounts and route */ quote: z.object({
|
|
28079
28480
|
/** Estimated output amount (base units) */ estimatedAmount: z.string().min(1, 'estimatedAmount must be a non-empty string').regex(/^\d+$/, 'estimatedAmount must be a numeric string'),
|
|
28080
28481
|
/** Guaranteed minimum output amount (base units) */ minAmount: z.string().min(1, 'minAmount must be a non-empty string').regex(/^\d+$/, 'minAmount must be a numeric string'),
|
|
28081
|
-
/** Route information from DEX aggregator */ route:
|
|
28082
|
-
provider: z.string().min(1, 'provider must be a non-empty string'),
|
|
28083
|
-
steps: z.array(z.unknown())
|
|
28084
|
-
})
|
|
28482
|
+
/** Route information from DEX aggregator */ route: responseSwapRouteSchema
|
|
28085
28483
|
}),
|
|
28086
28484
|
/** Fee context indicating where fees should be collected */ feeContext: quoteFeeContextSchema
|
|
28087
28485
|
});
|
|
@@ -28297,19 +28695,6 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
|
|
|
28297
28695
|
}).min(1, 'toChain must be a non-empty string if provided').optional(),
|
|
28298
28696
|
apiKey: apiKeySchema.optional()
|
|
28299
28697
|
});
|
|
28300
|
-
/**
|
|
28301
|
-
* Zod schema for validating CreateSwapResponse payloads.
|
|
28302
|
-
*/ const createSwapFeeItemSchema = z.object({
|
|
28303
|
-
token: z.string({
|
|
28304
|
-
required_error: 'fee token is required',
|
|
28305
|
-
invalid_type_error: 'fee token must be a string'
|
|
28306
|
-
}).min(1, 'fee token must be a non-empty string'),
|
|
28307
|
-
amount: feeAmountSchema,
|
|
28308
|
-
decimals: z.number().int('fee token decimals must be an integer').nonnegative('fee token decimals must be a non-negative integer').optional(),
|
|
28309
|
-
symbol: z.string({
|
|
28310
|
-
invalid_type_error: 'fee token symbol must be a string'
|
|
28311
|
-
}).min(1, 'fee token symbol must be a non-empty string').optional()
|
|
28312
|
-
});
|
|
28313
28698
|
/**
|
|
28314
28699
|
* Developer fee item schema with basis field.
|
|
28315
28700
|
*/ const createSwapDeveloperFeeItemSchema = createSwapFeeItemSchema.extend({
|
|
@@ -28447,6 +28832,8 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
|
|
|
28447
28832
|
correlationId: z.preprocess((value)=>z.string().uuid().safeParse(value).success ? value : undefined, z.string().optional()),
|
|
28448
28833
|
config: createSwapRequestBaseSchema.shape.config.optional(),
|
|
28449
28834
|
fees: createSwapFeesSchema.optional(),
|
|
28835
|
+
// A route the SDK cannot parse is dropped instead of failing the swap.
|
|
28836
|
+
route: withFallback(responseSwapRouteSchema.optional(), undefined),
|
|
28450
28837
|
transaction: createSwapTransactionSchema
|
|
28451
28838
|
});
|
|
28452
28839
|
|
|
@@ -29574,6 +29961,16 @@ createTokenRegistry();
|
|
|
29574
29961
|
name: 'USDC',
|
|
29575
29962
|
version: '2'
|
|
29576
29963
|
},
|
|
29964
|
+
Cronos: {
|
|
29965
|
+
chainId: Cronos.chainId,
|
|
29966
|
+
name: 'USDC',
|
|
29967
|
+
version: '2'
|
|
29968
|
+
},
|
|
29969
|
+
Morph: {
|
|
29970
|
+
chainId: Morph.chainId,
|
|
29971
|
+
name: 'USDC',
|
|
29972
|
+
version: '2'
|
|
29973
|
+
},
|
|
29577
29974
|
Arc_Testnet: {
|
|
29578
29975
|
chainId: ArcTestnet.chainId,
|
|
29579
29976
|
name: 'USDC',
|
|
@@ -29662,6 +30059,7 @@ const optionalSwapChainIdentifierField = swapChainIdentifierField.optional();
|
|
|
29662
30059
|
* - customFee: Optional fee configuration
|
|
29663
30060
|
* - apiKey: Optional credential string
|
|
29664
30061
|
* - kitKey: Optional credential string (deprecated alias for apiKey)
|
|
30062
|
+
* - batchTransactions: Optional boolean to opt out of atomic batching
|
|
29665
30063
|
*/ const swapConfigSchema = z.object({
|
|
29666
30064
|
allowanceStrategy: allowanceStrategySchema.optional(),
|
|
29667
30065
|
slippageBps: z.number().int().min(0).optional(),
|
|
@@ -29672,7 +30070,10 @@ const optionalSwapChainIdentifierField = swapChainIdentifierField.optional();
|
|
|
29672
30070
|
})(z.string())).optional(),
|
|
29673
30071
|
customFee: swapCustomFeeSchema.optional(),
|
|
29674
30072
|
apiKey: z.string().optional(),
|
|
29675
|
-
kitKey: z.string().optional()
|
|
30073
|
+
kitKey: z.string().optional(),
|
|
30074
|
+
batchTransactions: z.boolean({
|
|
30075
|
+
invalid_type_error: 'batchTransactions must be a boolean'
|
|
30076
|
+
}).optional()
|
|
29676
30077
|
});
|
|
29677
30078
|
const swapDestinationSchema = z.object({
|
|
29678
30079
|
chain: optionalSwapChainIdentifierField,
|
|
@@ -29865,7 +30266,7 @@ new Set(Object.values(Blockchain));
|
|
|
29865
30266
|
registerKit(`${pkg$2.name}/${pkg$2.version}`);
|
|
29866
30267
|
|
|
29867
30268
|
var name$1 = "@circle-fin/earn-kit";
|
|
29868
|
-
var version$1 = "1.
|
|
30269
|
+
var version$1 = "1.10.0";
|
|
29869
30270
|
var pkg$1 = {
|
|
29870
30271
|
name: name$1,
|
|
29871
30272
|
version: version$1};
|
|
@@ -31369,7 +31770,7 @@ registerKit(`${pkg$1.name}/${pkg$1.version}`);
|
|
|
31369
31770
|
};
|
|
31370
31771
|
|
|
31371
31772
|
var name = "@circle-fin/borrow-kit";
|
|
31372
|
-
var version = "1.
|
|
31773
|
+
var version = "1.1.1";
|
|
31373
31774
|
var pkg = {
|
|
31374
31775
|
name: name,
|
|
31375
31776
|
version: version};
|