@circle-fin/app-kit 1.16.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bridge.cjs CHANGED
@@ -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. `error.data` field
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
- // Check error.data field
2537
- if (error !== null && typeof error === 'object' && 'data' in error) {
2538
- if (typeof error.data === 'string' && /^0x[0-9a-f]{8}$/i.test(error.data)) {
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 = {}));
@@ -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
- * - CCTPv2 support (adapter contract deployed)
8313
- * - Mainnet only (no testnets)
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 CCTPv2 support (adapter contract deployed)
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 (CCTPv2)
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 CCTPv2 support
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
  };
@@ -12236,7 +12297,7 @@ function resolveOptions(options) {
12236
12297
  }
12237
12298
 
12238
12299
  var name$3 = "@circle-fin/bridge-kit";
12239
- var version$4 = "1.15.2";
12300
+ var version$4 = "1.15.3";
12240
12301
  var pkg$4 = {
12241
12302
  name: name$3,
12242
12303
  version: version$4};
@@ -14801,7 +14862,11 @@ function createNoopLogger() {
14801
14862
  tokenId: bytes32Hex,
14802
14863
  domainId: nonNegativeInteger,
14803
14864
  tokenAddress: zod.z.string(),
14804
- tokenManagerAddress: zod.z.string()
14865
+ tokenManagerAddress: zod.z.string(),
14866
+ // Operator-controlled per-chain kill switch (CCTPE-3979). Optional for
14867
+ // back-compat with older IRIS versions that do not surface it. Downstream
14868
+ // consumers in `findCCTPXDeployment` treat a missing value as `true`.
14869
+ enabled: zod.z.boolean().optional()
14805
14870
  });
14806
14871
  /**
14807
14872
  * Schema for one token entry in the token registry response.
@@ -15285,17 +15350,23 @@ function createNoopLogger() {
15285
15350
  /**
15286
15351
  * Find a token's deployment on the given CCTP domain.
15287
15352
  *
15353
+ * A deployment row with `enabled === false` is treated as missing: an IRIS
15354
+ * operator has flipped the per-chain kill switch (CCTPE-3979), so the SDK must
15355
+ * not route through it even though the row still exists in the registry. A
15356
+ * missing or `true` `enabled` value remains routable — the field is optional on
15357
+ * older IRIS versions and absence is read as "allowed".
15358
+ *
15288
15359
  * @param token - The registry token whose deployments are searched.
15289
15360
  * @param domain - The CCTP domain id to match.
15290
15361
  * @returns The matching {@link CCTPXTokenDeployment}, or `undefined` when the
15291
- * token has no deployment on that domain.
15362
+ * token has no deployment on that domain or the deployment is disabled.
15292
15363
  *
15293
15364
  * @example
15294
15365
  * ```typescript
15295
15366
  * const deployment = findCCTPXDeployment(token, 0)
15296
15367
  * ```
15297
15368
  */ function findCCTPXDeployment(token, domain) {
15298
- return token.deployments.find((deployment)=>deployment.domainId === domain);
15369
+ return token.deployments.find((deployment)=>deployment.domainId === domain && deployment.enabled !== false);
15299
15370
  }
15300
15371
 
15301
15372
  /**
@@ -15397,6 +15468,24 @@ function createNoopLogger() {
15397
15468
  }
15398
15469
  }
15399
15470
  })
15471
+ ],
15472
+ // The token is not deployed on one of the route chains, or an operator has
15473
+ // flipped the per-chain `enabled` kill switch on the IRIS deployment row.
15474
+ // Either way the route is permanently unavailable until the operator intervenes;
15475
+ // a retry at the same source/destination will keep returning this error.
15476
+ [
15477
+ 'TOKEN_NOT_SUPPORTED_ON_ROUTE',
15478
+ ({ sourceDomain, destinationDomain })=>new KitError({
15479
+ ...InputError.UNSUPPORTED_ROUTE,
15480
+ recoverability: 'FATAL',
15481
+ message: 'CCTPx fee quote rejected the route: the token is not supported on ' + 'the source or destination chain (missing deployment or operator-disabled).',
15482
+ cause: {
15483
+ trace: {
15484
+ sourceDomain,
15485
+ destinationDomain
15486
+ }
15487
+ }
15488
+ })
15400
15489
  ]
15401
15490
  ]);
15402
15491
  /**
@@ -23407,7 +23496,7 @@ const mockAttestationMessage = {
23407
23496
  return step;
23408
23497
  }
23409
23498
 
23410
- var version$3 = "1.14.1";
23499
+ var version$3 = "1.14.2";
23411
23500
  var pkg$3 = {
23412
23501
  version: version$3};
23413
23502
 
@@ -27658,7 +27747,7 @@ registerKit(`${pkg$4.name}/${pkg$4.version}`);
27658
27747
  };
27659
27748
 
27660
27749
  var name$2 = "@circle-fin/swap-kit";
27661
- var version$2 = "1.7.1";
27750
+ var version$2 = "1.8.0";
27662
27751
  var pkg$2 = {
27663
27752
  name: name$2,
27664
27753
  version: version$2};
@@ -28000,6 +28089,64 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
28000
28089
  }, {
28001
28090
  message: 'fee amount must be non-negative (>= 0)'
28002
28091
  });
28092
+ /**
28093
+ * Parses a display-only field leniently: a value `schema` rejects is replaced
28094
+ * with `fallback` instead of failing the response that carries it.
28095
+ * Implemented with `preprocess` rather than Zod's `.catch()` because static
28096
+ * analysis misreads `.catch` on the schema chain as an unhandled Promise
28097
+ * (S7785).
28098
+ */ const withFallback = (schema, fallback)=>zod.z.preprocess((value)=>schema.safeParse(value).success ? value : fallback, schema);
28099
+ const swapRouteTokenSchema = zod.z.object({
28100
+ symbol: zod.z.string(),
28101
+ address: zod.z.string(),
28102
+ decimals: zod.z.number()
28103
+ });
28104
+ const swapRouteMetadataSchema = zod.z.record(zod.z.unknown()).optional();
28105
+ const swapRouteStepSchema = zod.z.object({
28106
+ type: zod.z.string(),
28107
+ tool: zod.z.string(),
28108
+ toolName: zod.z.string(),
28109
+ fromToken: swapRouteTokenSchema,
28110
+ toToken: swapRouteTokenSchema,
28111
+ estimate: zod.z.object({
28112
+ fromAmount: zod.z.string(),
28113
+ toAmount: zod.z.string(),
28114
+ gasCostUSD: zod.z.string().optional()
28115
+ }),
28116
+ metadata: swapRouteMetadataSchema
28117
+ });
28118
+ /**
28119
+ * Strict schema for a `SwapRoute`. Module-private: service responses
28120
+ * parse routes leniently through {@link responseSwapRouteSchema}.
28121
+ */ const swapRouteSchema = zod.z.object({
28122
+ provider: zod.z.string().min(1, 'provider must be a non-empty string'),
28123
+ steps: zod.z.array(swapRouteStepSchema),
28124
+ metadata: swapRouteMetadataSchema
28125
+ });
28126
+ /**
28127
+ * Route details are display-only, so service responses parse them leniently:
28128
+ * steps or metadata in a shape the SDK does not know are dropped rather than
28129
+ * failing the quote or swap they describe. Steps are all-or-nothing: if any
28130
+ * step is malformed, `steps` is empty, so a route never silently loses a hop.
28131
+ */ const responseSwapRouteSchema = swapRouteSchema.extend({
28132
+ steps: withFallback(swapRouteSchema.shape.steps, []),
28133
+ metadata: withFallback(swapRouteMetadataSchema, undefined)
28134
+ });
28135
+ const createSwapFeeItemSchema = zod.z.object({
28136
+ token: zod.z.string({
28137
+ required_error: 'fee token is required',
28138
+ invalid_type_error: 'fee token must be a string'
28139
+ }).min(1, 'fee token must be a non-empty string'),
28140
+ amount: feeAmountSchema,
28141
+ decimals: zod.z.number().int('fee token decimals must be an integer').nonnegative('fee token decimals must be a non-negative integer').optional(),
28142
+ symbol: zod.z.string({
28143
+ invalid_type_error: 'fee token symbol must be a string'
28144
+ }).min(1, 'fee token symbol must be a non-empty string').optional(),
28145
+ // Descriptive metadata: a value the SDK cannot use is dropped rather than
28146
+ // failing the response that carries the fee.
28147
+ type: withFallback(zod.z.string().min(1).optional(), undefined),
28148
+ chain: withFallback(zod.z.string().min(1).optional(), undefined)
28149
+ });
28003
28150
  /**
28004
28151
  * Zod schema for validating API keys.
28005
28152
  *
@@ -28085,10 +28232,7 @@ const optionalChainIdentifierField = chainIdentifierField.optional();
28085
28232
  /** Quote information with estimated amounts and route */ quote: zod.z.object({
28086
28233
  /** 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
28234
  /** 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: zod.z.object({
28089
- provider: zod.z.string().min(1, 'provider must be a non-empty string'),
28090
- steps: zod.z.array(zod.z.unknown())
28091
- })
28235
+ /** Route information from DEX aggregator */ route: responseSwapRouteSchema
28092
28236
  }),
28093
28237
  /** Fee context indicating where fees should be collected */ feeContext: quoteFeeContextSchema
28094
28238
  });
@@ -28304,19 +28448,6 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
28304
28448
  }).min(1, 'toChain must be a non-empty string if provided').optional(),
28305
28449
  apiKey: apiKeySchema.optional()
28306
28450
  });
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
28451
  /**
28321
28452
  * Developer fee item schema with basis field.
28322
28453
  */ const createSwapDeveloperFeeItemSchema = createSwapFeeItemSchema.extend({
@@ -28454,6 +28585,8 @@ getQuoteRequestBaseSchema.superRefine(requireCrossChainQuoteToAddress);
28454
28585
  correlationId: zod.z.preprocess((value)=>zod.z.string().uuid().safeParse(value).success ? value : undefined, zod.z.string().optional()),
28455
28586
  config: createSwapRequestBaseSchema.shape.config.optional(),
28456
28587
  fees: createSwapFeesSchema.optional(),
28588
+ // A route the SDK cannot parse is dropped instead of failing the swap.
28589
+ route: withFallback(responseSwapRouteSchema.optional(), undefined),
28457
28590
  transaction: createSwapTransactionSchema
28458
28591
  });
28459
28592
 
@@ -29581,6 +29714,16 @@ createTokenRegistry();
29581
29714
  name: 'USDC',
29582
29715
  version: '2'
29583
29716
  },
29717
+ Cronos: {
29718
+ chainId: Cronos.chainId,
29719
+ name: 'USDC',
29720
+ version: '2'
29721
+ },
29722
+ Morph: {
29723
+ chainId: Morph.chainId,
29724
+ name: 'USDC',
29725
+ version: '2'
29726
+ },
29584
29727
  Arc_Testnet: {
29585
29728
  chainId: ArcTestnet.chainId,
29586
29729
  name: 'USDC',
@@ -29669,6 +29812,7 @@ const optionalSwapChainIdentifierField = swapChainIdentifierField.optional();
29669
29812
  * - customFee: Optional fee configuration
29670
29813
  * - apiKey: Optional credential string
29671
29814
  * - kitKey: Optional credential string (deprecated alias for apiKey)
29815
+ * - batchTransactions: Optional boolean to opt out of atomic batching
29672
29816
  */ const swapConfigSchema = zod.z.object({
29673
29817
  allowanceStrategy: allowanceStrategySchema.optional(),
29674
29818
  slippageBps: zod.z.number().int().min(0).optional(),
@@ -29679,7 +29823,10 @@ const optionalSwapChainIdentifierField = swapChainIdentifierField.optional();
29679
29823
  })(zod.z.string())).optional(),
29680
29824
  customFee: swapCustomFeeSchema.optional(),
29681
29825
  apiKey: zod.z.string().optional(),
29682
- kitKey: zod.z.string().optional()
29826
+ kitKey: zod.z.string().optional(),
29827
+ batchTransactions: zod.z.boolean({
29828
+ invalid_type_error: 'batchTransactions must be a boolean'
29829
+ }).optional()
29683
29830
  });
29684
29831
  const swapDestinationSchema = zod.z.object({
29685
29832
  chain: optionalSwapChainIdentifierField,
@@ -29872,7 +30019,7 @@ new Set(Object.values(Blockchain));
29872
30019
  registerKit(`${pkg$2.name}/${pkg$2.version}`);
29873
30020
 
29874
30021
  var name$1 = "@circle-fin/earn-kit";
29875
- var version$1 = "1.8.1";
30022
+ var version$1 = "1.9.0";
29876
30023
  var pkg$1 = {
29877
30024
  name: name$1,
29878
30025
  version: version$1};
@@ -31376,7 +31523,7 @@ registerKit(`${pkg$1.name}/${pkg$1.version}`);
31376
31523
  };
31377
31524
 
31378
31525
  var name = "@circle-fin/borrow-kit";
31379
- var version = "1.0.0";
31526
+ var version = "1.1.0";
31380
31527
  var pkg = {
31381
31528
  name: name,
31382
31529
  version: version};
package/bridge.d.cts CHANGED
@@ -899,10 +899,10 @@ declare enum Blockchain {
899
899
  *
900
900
  * Unlike the full {@link Blockchain} enum, SwapChain includes mainnet
901
901
  * networks and explicitly whitelisted testnets (e.g., {@link Arc_Testnet})
902
- * where adapter contracts are deployed (CCTPv2 support).
902
+ * where Adapter contracts are deployed.
903
903
  *
904
904
  * Dynamic validation via {@link isSwapSupportedChain} ensures chains
905
- * automatically work when adapter contracts and supported tokens are deployed.
905
+ * automatically work when Adapter contracts and supported tokens are deployed.
906
906
  *
907
907
  * @example
908
908
  * ```typescript
@@ -942,20 +942,22 @@ declare enum SwapChain {
942
942
  HyperEVM = "HyperEVM",
943
943
  Monad = "Monad",
944
944
  Arc = "Arc",
945
+ Cronos = "Cronos",
946
+ Morph = "Morph",
945
947
  Arc_Testnet = "Arc_Testnet"
946
948
  }
947
949
  /**
948
950
  * Chain definition that supports swap operations.
949
951
  *
950
952
  * @remarks
951
- * Expanded from 4 to ~18 supported chains based on:
952
- * - CCTPv2 support (adapter contract deployed)
953
+ * Expanded from 4 to supported mainnets and whitelisted testnets based on:
954
+ * - A deployed Adapter contract, configured directly or through CCTP v2
953
955
  * - Mainnet chains plus whitelisted testnets (e.g., Arc Testnet)
954
956
  *
955
957
  * Use `isSwapSupportedChain()` for runtime validation.
956
958
  */
957
959
  type SwapChainDefinition = ChainDefinition & {
958
- chain: Blockchain.Ethereum | Blockchain.Base | Blockchain.Polygon | Blockchain.Solana | Blockchain.Arbitrum | Blockchain.Optimism | Blockchain.Avalanche | Blockchain.Linea | Blockchain.Ink | Blockchain.World_Chain | Blockchain.Unichain | Blockchain.Plume | Blockchain.Sei | Blockchain.Sonic | Blockchain.XDC | Blockchain.HyperEVM | Blockchain.Monad | Blockchain.Arc | Blockchain.Arc_Testnet;
960
+ chain: Blockchain.Ethereum | Blockchain.Base | Blockchain.Polygon | Blockchain.Solana | Blockchain.Arbitrum | Blockchain.Optimism | Blockchain.Avalanche | Blockchain.Linea | Blockchain.Ink | Blockchain.World_Chain | Blockchain.Unichain | Blockchain.Plume | Blockchain.Sei | Blockchain.Sonic | Blockchain.XDC | Blockchain.HyperEVM | Blockchain.Monad | Blockchain.Arc | Blockchain.Cronos | Blockchain.Morph | Blockchain.Arc_Testnet;
959
961
  };
960
962
  /**
961
963
  * Chain identifier accepted by swap operations.
@@ -6975,7 +6977,7 @@ interface ServiceSwapConfig {
6975
6977
  *
6976
6978
  * @defaultValue true
6977
6979
  */
6978
- batchTransactions?: boolean;
6980
+ batchTransactions?: boolean | undefined;
6979
6981
  }
6980
6982
  /**
6981
6983
  * Parameters for initiating a swap operation through the Stablecoin Service.
@@ -7439,6 +7441,33 @@ interface SwapConfig {
7439
7441
  * `apiKey` is omitted, and `apiKey` takes precedence when both are set.
7440
7442
  */
7441
7443
  kitKey?: string;
7444
+ /**
7445
+ * Enable or disable atomic batched execution of the approval and swap.
7446
+ *
7447
+ * When `true` (or omitted), an EVM swap that needs an on-chain ERC-20
7448
+ * approval submits the approval and the swap as one atomic batch if the
7449
+ * connected wallet supports it (EIP-5792, or a signing strategy that
7450
+ * declares atomic batching). Set to `false` to force the sequential
7451
+ * approve-then-swap flow.
7452
+ *
7453
+ * @remarks
7454
+ * Has no effect on the gasless permit path, native-token swaps, or Solana,
7455
+ * which already execute as a single transaction. USDT input always uses the
7456
+ * sequential path because its allowance must be reset to zero first. The
7457
+ * batched path relies on the wallet's own gas estimation for the swap call;
7458
+ * set `false` if your wallet under-estimates gas for complex routes or
7459
+ * rejects batched calls.
7460
+ *
7461
+ * @defaultValue `undefined` (batching attempted when the wallet supports it)
7462
+ *
7463
+ * @example
7464
+ * ```typescript
7465
+ * const config: SwapConfig = {
7466
+ * batchTransactions: false, // force sequential approve → swap
7467
+ * }
7468
+ * ```
7469
+ */
7470
+ batchTransactions?: boolean | undefined;
7442
7471
  }
7443
7472
  /**
7444
7473
  * Resolved parameters for swap operations after validation and normalization.
package/bridge.d.mts CHANGED
@@ -899,10 +899,10 @@ declare enum Blockchain {
899
899
  *
900
900
  * Unlike the full {@link Blockchain} enum, SwapChain includes mainnet
901
901
  * networks and explicitly whitelisted testnets (e.g., {@link Arc_Testnet})
902
- * where adapter contracts are deployed (CCTPv2 support).
902
+ * where Adapter contracts are deployed.
903
903
  *
904
904
  * Dynamic validation via {@link isSwapSupportedChain} ensures chains
905
- * automatically work when adapter contracts and supported tokens are deployed.
905
+ * automatically work when Adapter contracts and supported tokens are deployed.
906
906
  *
907
907
  * @example
908
908
  * ```typescript
@@ -942,20 +942,22 @@ declare enum SwapChain {
942
942
  HyperEVM = "HyperEVM",
943
943
  Monad = "Monad",
944
944
  Arc = "Arc",
945
+ Cronos = "Cronos",
946
+ Morph = "Morph",
945
947
  Arc_Testnet = "Arc_Testnet"
946
948
  }
947
949
  /**
948
950
  * Chain definition that supports swap operations.
949
951
  *
950
952
  * @remarks
951
- * Expanded from 4 to ~18 supported chains based on:
952
- * - CCTPv2 support (adapter contract deployed)
953
+ * Expanded from 4 to supported mainnets and whitelisted testnets based on:
954
+ * - A deployed Adapter contract, configured directly or through CCTP v2
953
955
  * - Mainnet chains plus whitelisted testnets (e.g., Arc Testnet)
954
956
  *
955
957
  * Use `isSwapSupportedChain()` for runtime validation.
956
958
  */
957
959
  type SwapChainDefinition = ChainDefinition & {
958
- chain: Blockchain.Ethereum | Blockchain.Base | Blockchain.Polygon | Blockchain.Solana | Blockchain.Arbitrum | Blockchain.Optimism | Blockchain.Avalanche | Blockchain.Linea | Blockchain.Ink | Blockchain.World_Chain | Blockchain.Unichain | Blockchain.Plume | Blockchain.Sei | Blockchain.Sonic | Blockchain.XDC | Blockchain.HyperEVM | Blockchain.Monad | Blockchain.Arc | Blockchain.Arc_Testnet;
960
+ chain: Blockchain.Ethereum | Blockchain.Base | Blockchain.Polygon | Blockchain.Solana | Blockchain.Arbitrum | Blockchain.Optimism | Blockchain.Avalanche | Blockchain.Linea | Blockchain.Ink | Blockchain.World_Chain | Blockchain.Unichain | Blockchain.Plume | Blockchain.Sei | Blockchain.Sonic | Blockchain.XDC | Blockchain.HyperEVM | Blockchain.Monad | Blockchain.Arc | Blockchain.Cronos | Blockchain.Morph | Blockchain.Arc_Testnet;
959
961
  };
960
962
  /**
961
963
  * Chain identifier accepted by swap operations.
@@ -6975,7 +6977,7 @@ interface ServiceSwapConfig {
6975
6977
  *
6976
6978
  * @defaultValue true
6977
6979
  */
6978
- batchTransactions?: boolean;
6980
+ batchTransactions?: boolean | undefined;
6979
6981
  }
6980
6982
  /**
6981
6983
  * Parameters for initiating a swap operation through the Stablecoin Service.
@@ -7439,6 +7441,33 @@ interface SwapConfig {
7439
7441
  * `apiKey` is omitted, and `apiKey` takes precedence when both are set.
7440
7442
  */
7441
7443
  kitKey?: string;
7444
+ /**
7445
+ * Enable or disable atomic batched execution of the approval and swap.
7446
+ *
7447
+ * When `true` (or omitted), an EVM swap that needs an on-chain ERC-20
7448
+ * approval submits the approval and the swap as one atomic batch if the
7449
+ * connected wallet supports it (EIP-5792, or a signing strategy that
7450
+ * declares atomic batching). Set to `false` to force the sequential
7451
+ * approve-then-swap flow.
7452
+ *
7453
+ * @remarks
7454
+ * Has no effect on the gasless permit path, native-token swaps, or Solana,
7455
+ * which already execute as a single transaction. USDT input always uses the
7456
+ * sequential path because its allowance must be reset to zero first. The
7457
+ * batched path relies on the wallet's own gas estimation for the swap call;
7458
+ * set `false` if your wallet under-estimates gas for complex routes or
7459
+ * rejects batched calls.
7460
+ *
7461
+ * @defaultValue `undefined` (batching attempted when the wallet supports it)
7462
+ *
7463
+ * @example
7464
+ * ```typescript
7465
+ * const config: SwapConfig = {
7466
+ * batchTransactions: false, // force sequential approve → swap
7467
+ * }
7468
+ * ```
7469
+ */
7470
+ batchTransactions?: boolean | undefined;
7442
7471
  }
7443
7472
  /**
7444
7473
  * Resolved parameters for swap operations after validation and normalization.